How to retrieve max salary of employee from each department - sql

Consider the table Employee:
Department number Employee_id Salary
1 123 2000
1 234 3266
1 657 3265
2 546 2050
2 657 3000
2 121 6000
3 131 6500
3 141 5000
3 151 1050
Now I want to retrieve the employee_id having highest salary from each department. How to write the query for this?

A good way to approach these queries is using row_number():
select department_number, employee_id, salary
from (select e.*, row_number() over (partition by department order by salary desc) as seqnum
from employee e
) e
where seqnum = 1;
If you want to get multiple rows for a department when there are ties, then use dense_rank() or rank() instead of row_number().

Try this
SELECT Dept_Num,EmpID,Salary
from Employee
WHERE Salary IN (Select MAX(Salary) from Employee Group By Dept_Num)

Can you use the max statement:
Select departament_number,employee_id,salary
from employee
where salary in (select MAX(salary) from employee group by departament_number)

Related

how to find the maximum salary of employees in a specific department

I have a table named SalaryTable containing salaries of employee in various departments:
dept_id name salary
12 a 100
13 b 200
12 c 300
14 d 400
12 e 500
13 f 600
I need to find the maximum salary of each department with given department id AND the name of that person along with maximum salary.
I am using the following sql query for this
select dept_id, name, max(salary)
from SalaryTable
group by salary
But the above code is giving me error:
dept_id must be an aggregate expression or appear in GROUP BY clause
I am able to get the following table easily with this below query:
select dept_id, max(salary) as max_salary
from SalaryTable
group by salary
dept_id max_salary
12 500
13 600
14 400
but I also need the name of that person as:
REQUIRED OUTPUT
dept_id name max_salary
12 e 500
13 f 600
14 d 400
You appear to be learning SQL, so you can build on what you have. The following gets the maximum salary:
select dept_id, max(salary)
from SalaryTable
group by dept_id;
You can use this as a subquery, to get all matching names:
select st.*
from SalaryTable st join
(select dept_id, max(salary) as max_salary
from SalaryTable
group by dept_id
) std
on st.dept_id = std.dept_id and
st.salary = std.max_salary
use correlated subquery
select dept_id, name, salary
from SalaryTable a
where salary =(select max(salary) from SalaryTable b where a.dept_id=b.dept_id)
To be exact:
SELECT dept_id, NAME, salary FROM SalaryTable a
WHERE salary =(SELECT MAX(salary) FROM SalaryTable b WHERE a.dept_id=b.dept_id)
ORDER BY dept_id;
Also see try by joins because see this
Remember: Whatever you put in between select and from in single sql statement that must be used in the group by clause (That's what your error says!).
You can do it with NOT EXISTS:
select s.* from SalaryTable s
where not exists (
select 1 from SalaryTable
where dept_id = s.dept_id and salary > s.salary
)
order by s.dept_id
See the demo.
Results:
> dept_id | name | salary
> ------: | :--- | -----:
> 12 | e | 500
> 13 | f | 600
> 14 | d | 400

Trying to find an Oracle query to find nth highest salary and among them one with highest experience

I need to find name of the person with 3rd highest salary
The table in question is as follows:
Name Salary Experience
-------------------------------
Den 11000 114
Gerald 11000 148
Ellen 11000 174
Eleni 10500 149
Clara 10500 162
Janette 10000 156
Peter 10000 150
Hermann 10000 204
Harrison 10000 169
I need to find name of the person having max experience and in the 3rd highest salary bracket.
So evidently, 3rd highest salary is 10000 and max experience among those having 3rd highest salary is Hermann with exp of 204.
I have query to find the 3rd highest salary:
select name, salary, experience
from sal s1
where 3 - 1 = (select count(distinct salary)
from sal s2
where s2.salary > s1.salary);
But this query returns 4 rows and I need to know how I can filter it even further in this same query to find Hermann with exp of 204.
Use the DENSE_RANK analytic function to find the 3rd highest salary and the ROW_NUMBER (or RANK or DENSE_RANK) analytic function with a PARTITION BY clause to find the highest experience per salary. This only requires a single table/index scan.
Oracle Setup:
CREATE TABLE table_name ( Name, Salary, Experience ) AS
SELECT 'Den', 11000, 114 FROM DUAL UNION ALL
SELECT 'Gerald', 11000, 148 FROM DUAL UNION ALL
SELECT 'Ellen', 11000, 174 FROM DUAL UNION ALL
SELECT 'Eleni', 10500, 149 FROM DUAL UNION ALL
SELECT 'Clara', 10500, 162 FROM DUAL UNION ALL
SELECT 'Janette', 10000, 156 FROM DUAL UNION ALL
SELECT 'Peter', 10000, 150 FROM DUAL UNION ALL
SELECT 'Hermann', 10000, 204 FROM DUAL UNION ALL
SELECT 'Harrison', 10000, 169 FROM DUAL
Query: If you want to find "the person having max experience in the 3rd highest salary bracket":
SELECT Name, Salary, Experience
FROM (
SELECT t.*,
DENSE_RANK() OVER ( ORDER BY Salary DESC ) AS s_rank,
ROW_NUMBER() OVER ( PARTITION BY Salary ORDER BY Experience DESC )
AS Exp_rownum
FROM table_name t
)
WHERE s_rank = 3
AND Exp_rownum = 1;
If you swap the ROW_NUMBER() analytic function for either RANK() or DENSE_RANK() then this will return multiple people if they are tied with the joint highest experience in the 3rd highest salary bracket.
Output:
NAME | SALARY | EXPERIENCE
:------ | -----: | ---------:
Hermann | 10000 | 204
Query: If you want to find "the person having max experience and (also) in the 3rd highest salary bracket":
Just take the query above and remove the PARTITION BY clause.
SELECT Name, Salary, Experience
FROM (
SELECT t.*,
DENSE_RANK() OVER ( ORDER BY Salary DESC ) AS s_rank,
ROW_NUMBER() OVER ( ORDER BY Experience DESC ) AS Exp_rownum
FROM table_name t
)
WHERE s_rank = 3
AND Exp_rownum = 1;
Output:
(Note: if Herman's experience was 173 then this would not return any rows as Ellen would have the highest experience but she would not be in the 3rd highest salary bracket and Herman would be in the 3rd highest salary bracket but would only have the 2nd highest experience.)
NAME | SALARY | EXPERIENCE
:------ | -----: | ---------:
Hermann | 10000 | 204
db<>fiddle here
This query makes use of ROWNUM and MAX to find the right row. In the innermost sub-query the max experience is retreived for each salary level, ordered by salary descending, and then in the outer sub-query row numbers are added and this is joined with the original table to find the correct row(s)
SELECT s.name, s.salary, s.experience
FROM sal s
JOIN (SELECT s2.*, ROWNUM rnum
FROM (SELECT salary, max(experience) AS m_exp
FROM sal
GROUP BY salary
ORDER BY salary DESC) s2) s3 ON s3.salary = s.salary AND
s3.m_exp = s.experience AND
rnum = 3
You don't query on the experience. So you've to add a where-clause:
select name, salary, experience
from sal s1
where 3 - 1 = (select count(distinct salary)
from sal s2
where s2.salary > s1.salary)
and experience = (select max(experience) from sal)
UPDATE
The alternative (max experience within 3rd highest salary) should be:
select name, salary, experience
from sal s1
where 3 - 1 = (select count(distinct salary)
from sal s2
where s2.salary > s1.salary)
and experience = (select max(experience) from sal s3
where 3 - 1 = (select count(distinct salary)
from sal s4
where s4.salary > s3.salary)
)

Find the average value from the previous row and the current row for a same department id

I have 3 employees with the same departments. i wanted to find the average of their salaries based on the previous rows.
For example
Employee_id department_id salary avg(salary)
101 1 5000 5000
102 1 10000 7500
103 1 15000 10000
This is like for department id as 1 with first salary we find the average as 5000 for employee id 101 and for the same department id as 1 for the employee id as 102 , we find the average for the 2 values grouped by department id.
Hence
average is (10000+5000) /2 = 7500
But for the employee id as 103, department id is 1 and is grouped with all the above three values of amount.
Hence,
average of salary is (10000+5000+15000)/3 = 10000
The requirement is i have been asked to use query_partition_clause and order_by_clause.
Hence i tried as follows,
select avg(salary) OVER (partition by department_id ORDER BY department_id ) salary, department_id, salary from employee
But i am always getting the values by considering the department of 3 data values.
Henceforth can somebody help on this resolution?
Many Thanks for the help.
Use ORDER BY salary (or ORDER BY employee_id) rather than ORDER BY department_id:
Oracle Setup:
CREATE TABLE employees ( Employee_id, department_id, salary ) AS
SELECT 101, 1, 5000 FROM DUAL UNION ALL
SELECT 102, 1, 10000 FROM DUAL UNION ALL
SELECT 103, 1, 15000 FROM DUAL;
Query:
SELECT e.*,
AVG( salary ) OVER ( PARTITION BY department_id ORDER BY salary ) AS avg_salary
FROM employees e
Output:
EMPLOYEE_ID | DEPARTMENT_ID | SALARY | AVG_SALARY
----------: | ------------: | -----: | ---------:
101 | 1 | 5000 | 5000
102 | 1 | 10000 | 7500
103 | 1 | 15000 | 10000
db<>fiddle here
SELECT EMPLOYEE_ID,
DEPARTMENT_ID,
SALARY,
(SELECT AVG(SALARY)
FROM EMPLOYEES B
WHERE B.EMPLOYEE_ID <= A.EMPLOYEE_ID) AVG_SALARY
FROM EMPLOYEES A
GROUP BY EMPLOYEE_ID,
DEPARTMENT_ID,
SALARY
A sub query can be done in the query itself by filtering the employee ID. I hope I have helped with something.

I want to find the name who got the second maximum salary from a table?

I am new to Oracle.
I want to find the name who got the second maximum salary from a table?
Here the example table:
R.no name employee_id salary
201 Sanjay 78781 1000
202 Mohan 78782 2500
203 Viji 78783 5000
204 Vinay 78784 3000
205 Ishanth 78785 8000
select *
from (
select name,
salary,
dense_rank() over (order by salary desc) as rnk
from table_name
) t
where rnk = 2
SQLFiddle example: http://sqlfiddle.com/#!4/e93c3/1

SQL query to find Nth highest salary

I am referring to following query to find Nth highest salary of a employee.
select sal from emp t where &n = (select count(sal) from (select distinct sal
from emp) where t.sal<=sal);
One gentleman said this query works. Could someone please explain how equating a COUNT ( which really will be value between 1 to X where X is total distinct salaries) to &n produce this result ?
I am trying to understand how database handles this query internally and produces result ?
Thank you.
First, the query will return the nth lowest salary value. To return the nth highest salary value you must change t.sal <= sal to t.sal >= sal.
Next, this query works by first finding the distinct list of salary values as one derived table and then determines the number of employees that have a salary less than each one in this list. t.sal <= sal is taking the derived table (which most databases would require have an alias) and comparing each value against the outer emp table. It should be noted that this will return multiple rows in the case of a tie.
To manually trace the output, we need some inputs:
Alice | 200
Bob | 100
Charlie | 200
Danielle | 150
Select Distinct sal
From emp
Gives us
200
100
150
Now we analyze each row in the outer table
Alice - There are 3 distinct salary values less than or equal to 200
Bob - 1 rows <= 100
Charlie - 3 rows <= 200
Danielle - 2 row <= 150
Thus, for each salary value we get the following counts (and reordered by count):
Bob 1
Danielle 2
Charlie 3
Alice 3
The most important aspect that I think you are overlooking is that the outer emp table is correlated to the inner count calculation (which is why it is called a correlated subquery). I.e., for each row in the outer emp table, a new count is calculated for that row's salary via t.sal <= sal. Again, most database systems would require the inner most query to have an alias like so (note the As Z alias):
Select sal
From emp As t
Where &n = (
Select Count(Z.sal)
From (
Select Distinct sal
From emp
) As Z
Where t.sal <= Z.sal
)
select sal
from (
select sal,
dense_rank() over (order by sal desc) as rnk
) t
where rnk = 5;
Replace where rnk = 5 with whatever "nth" you want.
To get the nth highest salary value just put the value of 'N'.
Select Min(Salary) From (Select Top N * From Table_Name Order by Salary Desc);
SELECT TOP 1 salary
FROM (
SELECT DISTINCT TOP n salary
FROM employee
ORDER BY salary DESC) a
ORDER BY salary
where n > 1 (n is always
SELECT Max(Salary) as Salary
FROM employee
where Salary Not in
(SELECT TOP N Salary FROM employee ORDER BY Salary DESC)
where N is defined by you.
So let's say you have the following salaries in the table employee:
Here employeeID and Salary are the columns of employee table.
EmployeeID Salary
101 25,000
154 89,000
987 42,000
450 12,000
954 50,000
If we want to see the fourth-highest salary
Salary
25,000
Query return fourth highest salary.
In the database record data entries like
employ_id NAME salary
101 Henry 24000
102 Smith 24000
105 Roy 17000
106 Robbin 15000
702 Mac 2500
708 Bill 2100
709 Kane 2000
710 Ted 2000
here Some of employees having same salary then how to calculate nth (highest/lowest)salary
for the calculation of 3rd highest salary
select * from emloyees where salary in (select salary from (select rownum rank , salary from (select distinct salary from employees order by salary **desc**)) where rank =3;
ans = 15000
similarly to calculate 3rd lowest salary
Type same Query with a small change instead of desc type asc
select * from emloyees where salary in (select salary from (select rownum rank , salary from (select distinct salary from employees order by salary **asc**)) where rank =3;
Hope This will help you
Change nth highest salary value just put the value of 'N'
SELECT e1.EmployeeName, e1.EmployeeSalary from Employee e1
where N = (
select COUNT(e2.EmployeeSalary) from Employee e2 where e2.EmployeeSalary >= e1.EmployeeSalary)
There are so many ways to achieve this:-
1)
Select Top(1) sal from emp
where sal not in (select DISTINCT top(n-1) sal from emp order by sal desc)
2)
select salary
from (
select salary,
roe_number() over (order by salary ) as row from emp
) emp1
where row= n;
This query will not work if multiple rows have the same values one after another.
3)
select salary
from (
select salary,
dense_rank() over (order by salary ) as row from emp
) emp1
where row= n;
This will create a unique row number for all unique salary amounts.
4)
Select Min(sal) From
(Select DISTINCT Top n * From emp Order by sal Desc)as emp1;
5)
SELECT * FROM emp Emp1
WHERE (n-1) = (
SELECT COUNT(DISTINCT(Emp2.Sal))
FROM emp Emp2
WHERE Emp2.Sal > Emp1.Sal)
select salary
from (Select ROW_NUMBER() over(order by salary desc) as row ,salary from Employee)as temp
where row=2;
---2nd highest salary
n donated as nth number you want. like : i want second highest so my query will be
n=2
SELECT salary FROM Employee ORDER BY Salary DESC LIMIT 1,1
replace n with you number
SELECT salary FROM Employee ORDER BY Salary DESC LIMIT n-1,1
Query:
select
ename
,sal
,dense_rank() over (order by sal desc) ranking
from emp;
output:
ENAME SAL RANKING
KING 5000 1
FORD 3000 2
SCOTT 3000 2
JONES 2975 3
CLARK 2850 4
BLAKE 2850 4
ALLEN 1600 5
Wrap a filter around and pick out the Nth highest salary, say the 4th highest salary.
Query:
select *
from
(
select ename
,sal
,dense_rank() over (order by sal desc) ranking
from emp
)
where ranking = 4 -- Replace 4 with any value of N
output:
ENAME SAL RANKING
BLAKE 2850 4
CLARK 2850 4