Oracle SQL : FROM keyword not found where expected - sql

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>

Related

What's the meaning of this Oracle SQL code?

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>

SQL not correct end failure [duplicate]

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>

Oracle- sql query to print odd number of rows when we do not have number data type columns

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>

How to use rank to get the latest bonus record

currently I am using the below query to get the previous year’s bonus amount for the employees. But I am facing some issues, so I am trying to get the latest element entry value(screen entry value) for the element ‘xyz bonus’ using the RANK() function. Please help. Thanks.
Select
Pam.assignment_number,
Peev.screen_entry_value as bonus_amount
From
Per_all_assignments_m Pam,
Pay_element_entries_f peef,
Pay_element_types_tl petl,
Pay_element_entry_values_f peev
Where
Pam.Person_id=peef.person_id
and peef.element_type_id = petl. element_type_id
And peef.element_entry_id = peev. element_entry_id
And petl.language=‘US’
And to_char(peef.effective_start_date,’yyyy’)=(to_char(sysdate,’yyyy’)-1)
And to_char(peev.effective_start_date,’yyyy’)=(to_char(sysdate,’yyyy’)-1)
And petl.element_name = ‘xyz bonus’
As I don't have your tables, I'm using Scott's sample EMP table.
In there, rows sorted by salaries per department look like this:
SQL> select deptno,
2 ename,
3 sal,
4 rank() over (partition by deptno order by sal desc) rn
5 from emp
6 order by deptno,
7 sal desc;
DEPTNO ENAME SAL RN
---------- ---------- ---------- ----------
10 KING 10000 1
10 CLARK 2450 2
10 MILLER 1300 3
20 SCOTT 3000 1
20 FORD 3000 1
20 JONES 2975 3
20 ADAMS 1100 4
20 SMITH 920 5
30 BLAKE 2850 1
30 ALLEN 1600 2
30 TURNER 1500 3
30 MARTIN 1250 4
30 WARD 1250 4
30 JAMES 950 6
14 rows selected.
SQL>
If you want to fetch the highest salary per department, you'd then
SQL> select deptno, ename, sal
2 from (select deptno,
3 ename,
4 sal,
5 rank() over (partition by deptno order by sal desc) rn
6 from emp
7 )
8 where rn = 1;
DEPTNO ENAME SAL
---------- ---------- ----------
10 KING 10000
20 SCOTT 3000
20 FORD 3000
30 BLAKE 2850
SQL>
I guess that's what you are looking for.
Your query might then look like this:
Select
Pam.assignment_number,
Peev.screen_entry_value as bonus_amount,
rank() over (partition by pam.assignment_number order by peev.screen_entry_value desc) rn
From
...
Now, use it as an inline view (or a CTE) and fetch desired values.
If that's not what you are looking for, please, post sample data and desired result.

SQL -- Display 2nd highest salary for each dept, if employee having same salary then display salary with least empno

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