Get the name of the employee with the second highest salary [duplicate] - sql

This question already has answers here:
How to find the employee with the second highest salary?
(5 answers)
Closed 3 years ago.
I have to get the name of employee with the second highest salary the table name from where I am fetching is emp. I know the query for second highest salary which is
select max(sal)
from emp
where sal < (select max(sal) from emp)
it works and it returns the right answer.
But I have to get the name of the employee as well. I simply tried
select name, max(sal)
from emp
where sal < (select max(sal) from emp)
I get this error:
ORA-00937: not a single-group group function
how can i remove the error in order to get the name and salary both.
thank you to anyone who helps.

You can use
select name,sal from emp where sal = (select max(sal) from emp where sal < (select max(sal) from emp));

use this :
with cte (
select ROW_NUMBER() over(order by sal desc)rnum ,name,sal from emp )
select * from cte where rnum = 2

You can get this easily with a window function. Try something like this:
SELECT name, sal
FROM emp
QUALIFY RANK OVER(ORDER BY sal DESC) = 2
This will order your rows by Salary and then give each row a ranking. Then it will return the rows with ranking = 2.
If you want to ensure you only get one row back, change RANK to ROW_NUMBER.

Related

from keyword error in oracle apex site

I have tried checking all the duplicate answers provided in this site but couldn't able to come up with rectifying my error could you guys help me out on this?
Getting this error
ORA-00923: FROM keyword not found where expected
SELECT TOP 1 sal FROM emp WHERE sal in
(SELECT DISTINCT TOP 3 sal FROM emp ORDER BY sal DESC)
ORDER BY sal ASC;
I am solving this using oracle apex site
You appear to want to find thew record with the third-lowest salary.
You can use a subquery to assign an analytic rank to each salary, and then filter on that:
select * from (
select e.*, dense_rank() over (order by sal desc) as rnk
from emp e
)
where rnk = 3;
From 12c you can use the offset and fetch syntax to do the same thing:
select * from emp
order by sal desc
offset 3 rows
fetch first row only;
You need to decide how to deal with ties though - if more than one employee shares that third-lowest salary; or even if the lowest and second lowest are awarded to more than one person. Depending on what you want to happen you can look at variations of the 12c row-limiting syntax, and other analytic functions - row_number(), dense_rank() - and their windowing options.
I was able to get my query now
SELECT A.* FROM emp A where 3 =(SELECT COUNT(DISTINCT sal) FROM emp B WHERE A.sal <= B.sal);
Yet another option, using analytic function:
WITH ranks
AS (SELECT empno, DENSE_RANK () OVER (ORDER BY sal DESC) rnk FROM emp)
SELECT e.*
FROM emp e, ranks r
WHERE e.empno = r.empno
AND r.rnk = 3;

How can I select the record with the 2nd highest salary in database Oracle?

Suppose I have a table employee with id, user_name, salary. How can I select the record with the 2nd highest salary in Oracle?
I googled it, find this solution, is the following right?:
select sal from
(select rownum n,a.* from
( select distinct sal from emp order by sal desc) a)
where n = 2;
RANK and DENSE_RANK have already been suggested - depending on your requirements, you might also consider ROW_NUMBER():
select * from (
select e.*, row_number() over (order by sal desc) rn from emp e
)
where rn = 2;
The difference between RANK(), DENSE_RANK() and ROW_NUMBER() boils down to:
ROW_NUMBER() always generates a unique ranking; if the ORDER BY clause cannot distinguish between two rows, it will still give them different rankings (randomly)
RANK() and DENSE_RANK() will give the same ranking to rows that cannot be distinguished by the ORDER BY clause
DENSE_RANK() will always generate a contiguous sequence of ranks (1,2,3,...), whereas RANK() will leave gaps after two or more rows with the same rank (think "Olympic Games": if two athletes win the gold medal, there is no second place, only third)
So, if you only want one employee (even if there are several with the 2nd highest salary), I'd recommend ROW_NUMBER().
If you're using Oracle 8+, you can use the RANK() or DENSE_RANK() functions like so
SELECT *
FROM (
SELECT some_column,
rank() over (order by your_sort_column desc) as row_rank
) t
WHERE row_rank = 2;
This query works in SQL*PLUS to find out the 2nd Highest Salary -
SELECT * FROM EMP
WHERE SAL = (SELECT MAX(SAL) FROM EMP
WHERE SAL < (SELECT MAX(SAL) FROM EMP));
This is double sub-query.
I hope this helps you..
WITH records
AS
(
SELECT id, user_name, salary,
DENSE_RANK() OVER (PARTITION BY id ORDER BY salary DESC) rn
FROM tableName
)
SELECT id, user_name, salary
FROM records
WHERE rn = 2
DENSE_RANK()
You should use something like this:
SELECT *
FROM (select salary2.*, rownum rnum from
(select * from salary ORDER BY salary_amount DESC) salary2
where rownum <= 2 )
WHERE rnum >= 2;
select * from emp where sal=(select max(sal) from emp where sal<(select max(sal) from emp))
so in our emp table(default provided by oracle) here is the output
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
7698 BLAKE MANAGER 7839 01-MAY-81 3000 30
7788 SCOTT ANALYST 7566 19-APR-87 3000 20
7902 FORD ANALYST 7566 03-DEC-81 3000 20
or just you want 2nd maximum salary to be displayed
select max(sal) from emp where sal<(select max(sal) from emp)
MAX(SAL)
3000
select * FROM (
select EmployeeID, Salary
, dense_rank() over (order by Salary DESC) ranking
from Employee
)
WHERE ranking = 2;
dense_rank() is used for the salary has to be same.So it give the proper output instead of using rank().
select Max(Salary) as SecondHighestSalary from Employee where Salary not in
(select max(Salary) from Employee)
I would suggest following two ways to implement this in Oracle.
Using Sub-query:
select distinct SALARY
from EMPLOYEE e1
where 1=(select count(DISTINCT e2.SALARY) from EMPLOYEE e2 where
e2.SALARY>e1.SALARY);
This is very simple query to get required output. However, this query is quite slow as each salary in inner query is compared with all distinct salaries.
Using DENSE_RANK():
select distinct SALARY
from
(
select e1.*, DENSE_RANK () OVER (order by SALARY desc) as RN
from EMPLOYEE e
) E
where E.RN=2;
This is very efficient query. It works well with DENSE_RANK() which assigns consecutive ranks unlike RANK() which assigns next rank depending on row number which is like olympic medaling.
Difference between RANK() and DENSE_RANK():
https://oracle-base.com/articles/misc/rank-dense-rank-first-last-analytic-functions
I believe this will accomplish the same result, without a subquery or a ranking function:
SELECT *
FROM emp
ORDER BY sal DESC
LIMIT 1
OFFSET 2
This query helps me every time for problems like this. Replace N with position..
select *
from(
select *
from (select * from TABLE_NAME order by SALARY_COLUMN desc)
where rownum <=N
)
where SALARY_COLUMN <= all(
select SALARY_COLUMN
from (select * from TABLE_NAME order by SALARY_COLUMN desc)
where rownum <=N
);
select * from emp where sal = (
select sal from
(select rownum n,a.sal from
( select distinct sal from emp order by sal desc) a)
where n = 2);
This is more optimum, it suits all scenarios...
select max(Salary) from EmployeeTest where Salary < ( select max(Salary) from EmployeeTest ) ;
this will work for all DBs.
You can use two max function. Let's say get data of userid=10 and its 2nd highest salary from SALARY_TBL.
select max(salary) from SALARY_TBL
where
userid=10
salary <> (select max(salary) from SALARY_TBL where userid=10)
Replace N with your Highest Number
SELECT *
FROM Employee Emp1
WHERE (N-1) = (
SELECT COUNT(DISTINCT(Emp2.Salary))
FROM Employee Emp2
WHERE Emp2.Salary > Emp1.Salary)
Explanation
The query above can be quite confusing if you have not seen anything like it before – the inner query is what’s called a correlated sub-query because the inner query (the subquery) uses a value from the outer query (in this case the Emp1 table) in it’s WHERE clause.
And Source
I have given the answer here
By the way I am flagging this Question as Duplicate.
Syntax it for Sql server
SELECT MAX(Salary) as 'Salary' from EmployeeDetails
where Salary NOT IN
(
SELECT TOP n-1 (SALARY) from EmployeeDetails ORDER BY Salary Desc
)
To get 2nd highest salary of employee then we need replace “n” with 2 our query like will be this
SELECT MAX(Salary) as 'Salary' from EmployeeDetails
where Salary NOT IN
(
SELECT TOP 1 (SALARY) from EmployeeDetails ORDER BY Salary Desc
)
3rd highest salary of employee
SELECT MAX(Salary) as 'Salary' from EmployeeDetails
where Salary NOT IN
(
SELECT TOP 2 (SALARY) from EmployeeDetails ORDER BY Salary Desc
)
SELECT * FROM EMP WHERE SAL=(SELECT MAX(SAL) FROM EMP WHERE SAL<(SELECT MAX(SAL) FROM EMP));
(OR)
SELECT ENAME ,SAL FROM EMP ORDER BY SAL DESC;
(OR)
SELECT * FROM(SELECT ENAME,SAL ,DENSE_RANK()
OVER(PARTITION BY DEPTNO ORDER BY SAL DESC) R FROM EMP) WHERE R=2;
select salary from EmployeeDetails order by salary desc limit 1 offset (n-1).
If you want to find 2nd highest than replace n with that 2.

Display columns based on sub query

I want to display the name of department with highest SUM of salary.
I am using oracle sql and the table structure is Dept(Deptno,Dname,Loc) and Emp(Empno,Ename,Job,Salary,Deptno).
The query I use was
select Dname
from Dept
where Deptno=
( select Deptno
from Emp
where rownum=1
group by Deptno
order by sum(Salary) Desc
);
This gives an error:
Right parenthesis missing.
When I run the sub-query alone, it successfully returns a Deptno. But with the parent query, I get the above error.
What is the problem and what can be the possible solution?
select dname
from (select dname, rank() over (order by sum(salary) desc) rnk
from dept d
inner join emp e
on e.deptno = d.deptno
group by dname, e.deptno
)
where rnk = 1;
note, in your example putting where rownum=1 where you did is a huge bug. it would mean pick 1 random row and sort it (not really the highest salary row..just any old row)
my solution may get over 1 row if 2 deptartments have the same highest salary. you can use row_number() instead of rank() to just pick one if you want.

Combining columns

I am trying to do the following:
I have a table with ename, job, deptno, and sal. I am trying to initiate a query that returns the top earners of each department. I have done this with grouping and a subquery. However, I also want to display the average sal by deptno. So the following would be the result:
"ename" "dept" "sal" "average of dept"
sal 20 1000 500
kelly 30 2000 800
mika 40 3000 400
this might be impossible since the average does not associate with the other rows.
any suggestion would be appreciated. Thanks. I am using Oracle 10g to run my queries.
You could use analytic functions:
WITH RankedAndAveraged AS (
SELECT
ename,
dept,
sal,
RANK() OVER (PARTITION BY dept ORDER BY sal DESC) AS rnk,
AVG(sal) OVER (PARTITION BY dept) AS "average of dept"
FROM atable
)
SELECT
ename,
dept,
sal,
"average of dept"
FROM RankedAndAveraged
WHERE rnk = 1
This may return more than one employee per department if all of them have the same maximum value of sal. You can replace RANK() with ROW_NUMBER() if you only want one person per department (in which case you could also further extend ORDER BY by specifying additional sorting criteria to pick the top item, otherwise it will be picked randomly from among those with the maximum salary).
This should work. The only trick is that if you have several employees with the maximum salary in a department, it will show all of them.
SELECT t.ename, t.deptno, mx.sal as sal, mx.avg_sal as avg_sal
FROM tbl t,
(SELECT MAX(sal) AS sal, AVG(sal) AS avg_sal, deptno
FROM tbl
GROUP BY deptno) mx
WHERE t.deptno = mx.deptno AND t.sal = mx.sal
Not sure about Oracle, haven't used it in about 10 years, but something like this should be possible:
SELECT
ename, deptno, sal,
(SELECT AVG(T2.sal)
FROM tbl T2
WHERE T2.deptno = T.deptno
) AS average_of_dept
FROM tbl T
GROUP BY deptno
HAVING sal = MAX(sal)

How would I find the second largest salary from the employee table? [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
How would I go about querying for the second largest salary from all employees in my Employee table?
Try this:
SELECT max(salary)
FROM emptable
WHERE salary < (SELECT max(salary)
FROM emptable);
Simple Answer:
SELECT distinct(sal)
FROM emp
ORDER BY sal DESC
LIMIT 1, 1;
You will get only the second max salary.
And if you need any 3rd or 4th or Nth value you can increase the first value followed by LIMIT (n-1) ie. for 4th salary : LIMIT 3, 1;
Most of the other answers seem to be db specific.
General SQL query should be as follows:
select
sal
from
emp a
where
N = (
select
count(distinct sal)
from
emp b
where
a.sal <= b.sal
)
where
N = any value
and this query should be able to work on any database.
Try something like:
SELECT TOP 1 compensation FROM (
SELECT TOP 2 compensation FROM employees
ORDER BY compensation DESC
) AS em ORDER BY compensation ASC
Essentially:
Find the top 2 salaries in descending order.
Of those 2, find the top salary in ascending order.
The selected value is the second-highest salary.
If the salaries aren't distinct, you can use SELECT DISTINCT TOP ... instead.
Maybe you should use DENSE_RANK.
SELECT *
FROM (
SELECT
[Salary],
(DENSE_RANK()
OVER
(
ORDER BY [Salary] DESC)) AS rnk
FROM [Table1]
GROUP BY [Num]
) AS A
WHERE A.rnk = 2
To find second max salary from employee,
SELECT MAX(salary) FROM employee
WHERE salary NOT IN (
SELECT MAX (salary) FROM employee
)
To find first and second max salary from employee,
SELECT salary FROM (
SELECT DISTINCT(salary) FROM employee ORDER BY salary DESC
) WHERE rownum<=2
This queries are working fine because i have used
select max(Emp_Sal)
from Employee a
where 1 = ( select count(*)
from Employee b
where b.Emp_Sal > a.Emp_Sal)
Yes running man.
//To select name of employee whose salary is second highest
SELECT name
FROM employee WHERE salary =
(SELECT MIN(salary) FROM
(SELECT TOP (2) salary
FROM employee
ORDER BY salary DESC) )
select distinct(t1.sal)
from emp t1
where &n=(select count(distinct(t2.sal)) from emp t2 where t1.sal<=t2.sal);
Output:
Enter value for n: if you want 2nd highest ,enter 2; if you want 5,enter n=3
Try this:
SELECT
salary,
employeeid
FROM
employees
ORDER BY
salary DESC
LIMIT 2
Then just get the second row.
select * from compensation where Salary = (
select top 1 Salary from (
select top 2 Salary from compensation
group by Salary order by Salary desc) top2
order by Salary)
which will give you all rows with second highest salary, which a few people may share
select max(Salary) from Employee
where Salary
not in (Select Max(Salary) from Employee)
select max(Salary) from Employee
where Salary
not in (Select top4 salary from Employee);
because answer is as follows
max(5,6,7,8)
so 5th highest record will be displayed, first four will not be considered
select max(sal) from emp
where sal not in (select max(sal) from emp )
OR
select max(salary) from emp table
where sal<(select max(salary)from emp)
Try this:
select max(Emp_Sal)
from Employee a
where 1 = ( select count(*)
from Employee b
where b.Emp_Sal > a.Emp_Sal)
select * from emp
where sal=(select min(sal) from
(select sal from(select distinct sal from emp order by sal desc)
where rownum<=n));
n can be the value you want to see......
you can see all the fields of that person who having nth highest salary*strong text*
SELECT
TOP 1 salary
FROM
(
SELECT
TOP 2 salary
FROM
employees
) sal
ORDER BY
salary DESC;