This question already has answers here:
How do I limit the number of rows returned by an Oracle query after ordering?
(14 answers)
Closed 2 years ago.
SELECT * FROM workers ORDER BY salary DESC LIMIT 2;
I have this SQL statement to get the salary of the two best paid workers but I'm getting a SQL command was not ended correctly.
EDITED:
SELECT worker_id, last_name, job_id, salary
FROM (SELECT w.*,
rank() over (ORDER BY w.salary desc) rnk
FROM worker w
)
WHERE rnk <= 5;
Oracle doesn't support limit. Use;
select w.*
from workers w
order by salary desc
fetch first 2 rows only;
This works in the most recent versions of Oracle. In earlier versions, you can use a subquery:
select w.*
from (select w.*
from workers w
order by salary desc
) w
where rownum <= 2;
If your database doesn't support LIMIT clause, do it differently. For example:
select *
from (select w.*,
rank() over (order by w.salary desc) rnk
from workers w
)
where rnk <= 2;
For example (based on Scott's EMP table):
SQL> select empno, job, sal from emp order by sal desc;
EMPNO JOB SAL
---------- --------- ----------
7839 PRESIDENT 5000 --> two
7902 ANALYST 3000 --> highest
7788 ANALYST 3000 --> salaries (5000 and 3000)
7566 MANAGER 2975
7698 MANAGER 2850
7782 MANAGER 2450
7499 SALESMAN 1600
7844 SALESMAN 1500
7934 CLERK 1300
7521 SALESMAN 1250
7654 SALESMAN 1250
7876 CLERK 1100
7369 CLERK 1000
7900 CLERK 950
14 rows selected.
SQL> select *
2 from (select w.*,
3 rank() over (order by sal desc) rnk
4 from emp w
5 )
6 where rnk <= 2;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO RNK
---------- ---------- --------- ---------- ---------- ---------- ---------- ---------- ----------
7839 KING PRESIDENT 11/17/1981 5000 10 1
7788 SCOTT ANALYST 7566 12/09/1982 3000 20 2
7902 FORD ANALYST 7566 12/03/1981 3000 20 2
SQL>
Related
I've been learning Oracle SQL recently and I came across the following code:
SELECT *
FROM employees outer_emps
WHERE (2-1) = (
SELECT COUNT(*)
FROM employees inner_emps
WHERE inner_emps.salary > outer_emps.salary
);
Could someone please help me understand the syntax?
It returns employees whose salary is the 2nd highest.
For example:
SQL> select ename, sal from emp order by sal;
ENAME SAL
---------- ----------
SMITH 840
JAMES 950
ADAMS 1100
WARD 1250
MARTIN 1250
MILLER 1300
TURNER 1500
ALLEN 1600
CLARK 2450
BLAKE 2850
JONES 2975
SCOTT 3000 --> SCOTT and FORD have the 2nd highest salary
FORD 3000 -->
KING 5000 --> KING has the highest salary
14 rows selected.
SQL> select ename, sal
2 from emp outer_emps
3 where 1 = (select count(*) from emp inner_emps
4 where inner_emps.sal > outer_emps.sal);
ENAME SAL
---------- ----------
SCOTT 3000
FORD 3000
SQL>
If you used <, you'd get the 2nd lowest salary (that's James because SMITH's salary is 840 - the lowest - and JAMES follows with 950):
SQL> select ename, sal
2 from emp outer_emps
3 where 1 = (select count(*) from emp inner_emps
4 where inner_emps.sal < outer_emps.sal);
ENAME SAL
---------- ----------
JAMES 950
SQL>
I'd probably do it as follows; that's easier to understand:
SQL> with temp as
2 (select ename, sal,
3 rank() over (order by sal desc) rnk
4 from emp
5 )
6 select ename,sal from temp
7 where rnk = 2;
ENAME SAL
---------- ----------
SCOTT 3000
FORD 3000
SQL>
I was trying to print odd numbers of rows from my table without taking taking help of my numeric cloumns
when I try to execute this query I was getting only first row.
select * from emp3 where mod(rownum,2)=1;
emp3 is my table name.
and when I use my one of the numeric columns in place of rownum I was getting desired output.
select * from emp3 where mod(eid,2)=1 order by eid;
where eid is a numeric column in the table.
But what if do not have a numeric column and I want to print only odd number of rows from the table?
Help me!
Try to execute the below query
select * from (select rownum rn ,column from column_name) where mod(rn,2) <> 0
and please refer to this link for better understanding the concept of rownum https://www.youtube.com/watch?v=QMyw1jumGyQ
If the EID column isn't numeric, then use something that is. For example, ROW_NUMBER gives such an information:
SQL> with temp as
2 (select empno, ename, job sal,
3 row_number() over (order by null) rn
4 from emp
5 )
6 select *
7 from temp
8 where mod(rn, 2) = 1;
EMPNO ENAME SAL RN
---------- ---------- --------- ----------
7369 SMITH CLERK 1
7521 WARD SALESMAN 3
7654 MARTIN SALESMAN 5
7782 CLARK MANAGER 7
7839 KING PRESIDENT 9
7876 ADAMS CLERK 11
7902 FORD ANALYST 13
7 rows selected.
SQL>
Or even ROWNUM you already tried to use:
SQL> with temp as
2 (select empno, ename, job sal,
3 rownum rn
4 from emp
5 )
6 select *
7 from temp
8 where mod(rn, 2) = 1;
EMPNO ENAME SAL RN
---------- ---------- --------- ----------
7369 SMITH CLERK 1
7521 WARD SALESMAN 3
7654 MARTIN SALESMAN 5
7782 CLARK MANAGER 7
7839 KING PRESIDENT 9
7876 ADAMS CLERK 11
7902 FORD ANALYST 13
7 rows selected.
SQL>
I need to display 2nd highest salary for each dept, if employee having same salary then display salary with least empno .
I have emp table as below in which deptno 20 have 2nd highest salary 3000 for two empno 7788 and 7902 .
EMPNO ENAME JOB SAL DEPTNO
7698 BLAKE MANAGER 2850 30
7844 TURNER SALESMAN 1500 30
7499 ALLEN SALESMAN 1600 30
7654 MARTIN SALESMAN 1250 30
7521 WARD SALESMAN 1250 30
7900 JAMES CLERK 950 30
7788 SCOTT ANALYST 3000 20
7566 JONES MANAGER 2975 20
7369 SMITH CLERK 25000 20
7876 ADAMS CLERK 1100 20
7902 FORD ANALYST 3000 20
7839 KING PRESIDENT 5000 10
7934 MILLER CLERK 1300 10
7782 CLARK MANAGER 2450 10
I have written below code:
select * from (
select e.*, row_number() over (partition by deptno order by sal desc ) rn
from emp e
)where rn = 2;
I got below result. But as per my requirement, if any employee having same salary for that department, then salary with least employee id should be display but in my case empno 7902 is displayed. But I need to display salary with empno 7788:
EMPNO ENAME JOB SAL DEPTNO
7782 CLARK MANAGER 2450 10
7902 FORD ANALYST 3000 20
7499 ALLEN SALESMAN 1600 30
How to achieve this?
This query gives the correct result on MySql
select * from (
select e.*, row_number() over (partition by deptno order by sal desc, empno asc ) rn
from emp e
) s where rn = 2;
Result
EMPNO ENAME JOB SAL DEPTNO rn
7782 CLARK MANAGER 2450 10 2
7788 SCOTT ANALYST 3000 20 2
7499 ALLEN SALESMAN 1600 30 2
dbfiddle using Oracle
Try this..
You have to add empno in order by clause with asc
select * from ( select e.*, row_number() over (partition by deptno order by
sal desc,empno asc ) rn
from emp e) where rn = 2;
you can use RANK(). The difference between RANK() and ROW_NUMBER() is that RANK() will give same rank for same numbers, so you will see two 2 for department 20. Then you wrap it up with another ROW_NUMBER() to grab the least EMPNO:
SELECT * FROM (
SELECT
subq.EMPNO,
subq.DEPTNO,
ROW_NUMBER() OVER(PARTITION BY subq.DEPTNO ORDER BY EMPNO ASC) AS empno_rownum
FROM (
SELECT
salary.EMPNO,
salary.DEPTNO,
RANK() OVER(PARTITION BY salary.DEPTNO ORDER BY salary.SAL DESC) AS salary_rank
FROM salary
) AS subq
WHERE subq.salary_rank = 2
) AS subq2
WHERE subq2.empno_rownum = 1
And here is the result:
EMPNO DEPTNO salary_rank
7782 10 2
7788 20 2
7499 30 2
dataset taken from: Tim Hall's Oracle-Base rank/partition documentation Original assignment was to rank the salaries within a department. The MYRANK column is syntactic and introduced with
RANK() OVER (PARTITION BY deptno ORDER BY sal) AS myrank
But now I want to sort on the highest salary followed with all records within the same department. Then the second highest salary again followed with all the records in the same department. The order of dept is a kind of coincidental, it happens to be aligned with the order of highest salary per departnement.
I think I can solve this when the rank() is substituted for a max() like:
MAX() OVER (PARTITION BY DEPTNO ORDER BY SAL) AS MAX
and than a order by MAX, DEPTNO, but this fails with: invalid number of arguments
EMPNO DEPTNO SAL MYRANK
---------- ---------- ---------- ----------
7839 10 5000 3
7782 10 2450 2
7934 10 1300 1
7788 20 3000 4
7902 20 3000 4
7566 20 2975 3
7876 20 1100 2
7369 20 800 1
7698 30 2850 6
7499 30 1600 5
7844 30 1500 4
7654 30 1250 2
7521 30 1250 2
7900 30 950 1
You can put analytic functions in the order by, so you can do:
order by max(sal) over (partition by deptno) desc,
deptno,
sal desc
Notice that this has three keys in the order by. The deptno is needed in case two departments have the same highest salary.
my query as follows.
WITH CTE AS
(
SELECT EmpID, EmpName, EmpSalary,
RN = ROW_NUMBER() OVER (ORDER BY EmpSalary DESC)
FROM dbo.Salary
)
SELECT EmpID, EmpName, EmpSalary
FROM CTE
WHERE RN = #8thRow
I am getting error as
Error report -
SQL Error: ORA-00923: FROM keyword not found where expected
00923. 00000 - "FROM keyword not found where expected".
Can someone explain what is wrong with the code?
Wrong syntax; an example based on Scott's schema:
SQL> select ename, sal from emp order by sal;
ENAME SAL
---------- ----------
SMITH 920
JAMES 950
ADAMS 1100
WARD 1250
MARTIN 1250
MILLER 1300
TURNER 1500 -- 8th --> you need this one
ALLEN 1600
CLARK 2450
BLAKE 2850
JONES 2975 -- ...
SCOTT 3000 -- 3rd
FORD 3000 -- 2nd
KING 10000 -- 1st, when sort is DESCending
14 rows selected.
SQL> with cte as
2 (select empno, ename, sal,
3 row_number() over (order by sal desc) rn
4 from emp
5 )
6 select empno, ename, sal
7 from cte
8 where rn = 8;
EMPNO ENAME SAL
---------- ---------- ----------
7844 TURNER 1500
SQL>