I working with two tables
Employee ( empid integer, mgrid integer, deptid integer, salary integer)
Dept (deptid integer, deptname text)
I need to find top 3 employees (salary based), in every department. Result should have deptname, empid, salary sorted by deptname and then employee with high to low salary.
I appreciate all your help !!
There are two parts in this query. The inner and outer query.
First part, I am partitioning at deptid level and assigning the rank to the salaries in the descending order which solves your problem.
Second part is just a select on all the output fields by filtering out only the top three employees in each department.
Key point :- Assigning rank to the salaries for each department using ROW_NUMBER window function in the inner query solves the entire problem.
SELECT deptname,empid,salary
FROM
(
SELECT d.deptname,
e.empid,
e.salary,
ROW_NUMBER() OVER ( PARTITION BY e.deptid ORDER BY
e.salary DESC ) AS rank_salary_by_dept
FROM dept d, employee e
WHERE d.deptid = e.deptid
)
WHERE rank_salary_by_dept <= 3
ORDER BY deptname,rank_salary_by_dept;
Related
enter image description here
select Fname,Lname,salary,ssn
from Employee
where joptype='nurse' AND salary <= ALL (select salary
from Employee E,Nurses N
where E.Ssn=N.Ssn AND E.joptype='nurse' AND N.shift='morning')
I want to return a list of nurses name who works at morning and their salary is less than all nurses, or the opposite. I've tried both morning and night, also I've tried greater than all nurses. I think the problem is in the second where it seems like he ignores the shift condition.
You can use EXISTS to find the morning shifts and, from Oracle 12, you can use ORDER BY salary ASC FETCH FIRST ROW WITH TIES to find the matching employees with the lowest salary:
SELECT Fname,
Lname,
salary,
ssn
FROM Employee e
WHERE jobtype='nurse'
AND EXISTS( SELECT 1
FROM Nurses N
WHERE E.Ssn=N.Ssn
AND N.shift='morning' )
ORDER BY salary ASC
FETCH FIRST ROW WITH TIES;
or, if you want to check all nurses and find the minimum salary and then filter on morning shifts:
SELECT *
FROM (
SELECT Fname,
Lname,
salary,
ssn
FROM Employee
WHERE jobtype='nurse'
ORDER BY salary ASC
FETCH FIRST ROW WITH TIES
) e
WHERE EXISTS( SELECT 1
FROM Nurses N
WHERE E.Ssn=N.Ssn
AND N.shift='morning' )
If you want to use a JOIN, rather than EXISTS, then you can use:
SELECT e.Fname,
e.Lname,
e.salary,
e.ssn
FROM (
SELECT Fname,
Lname,
salary,
ssn
FROM Employee
WHERE jobtype='nurse'
ORDER BY salary ASC
FETCH FIRST ROW WITH TIES
) e
INNER JOIN Nurses N
ON E.Ssn=N.Ssn
WHERE N.shift='morning'
(However, if there are multiple entries in Nurses for an Employee then you will get duplicates using a JOIN that you would not get using EXISTS)
Or for your code, you appear to have the filter for shifts in the wrong place:
SELECT e.Fname,
e.Lname,
e.salary,
e.ssn
FROM Employee e
INNER JOIN Nurses n
ON (e.Ssn = n.Ssn)
WHERE e.jobtype='nurse'
AND n.shift='morning'
AND e.salary <= ALL ( SELECT salary
FROM Employee
WHERE jobtype='nurse' );
fiddle
This is how I understood it; what you said:
their salary is less than all nurses
probably means their average salary, so I used it in a subquery.
select e.fname, e.lname, e.salary, e.ssn
from employee e join nurse n on e.ssn = n.ssn
where e.joptype = 'nurse'
and n.shift = 'morning'
and salary < (select avg(salary) --> average salary of all nurses
from employee
where joptype = 'nurse'
);
(Just a remark: is it really joptype? Is it not a job?)
Maybe you could try it like here:
select
Fname, Lname, salary, ssn
from
Employee
where
joptype='nurse' AND
salary <= ( Select MIN(salary)
From Employee E
Inner join Nurses N ON(E.Ssn=N.Ssn)
Where E.joptype = 'nurse' AND
N.shift = 'morning'
)
... this will give you the list of nurses with salary less than or equal to the minimum salary among morning nurses..
I want to display the lowest earning employees of each department based on salary using min().
I have tables of employees with id, first name, last name, department id, salary
and departments, department_id, name department id from 1 to 5.
I am having trouble doing this, I only know how to start
SELECT name, surname from employees WHERE...
You would use min() for this. You would use window functions:
select e.*
from (select e.*,
rank() over (partition by department_id order by salary) as seqnum
from employees e
) e
where seqnum = 1
order by department_id;
With rank()over() ranking window function you can have your rows within a group ranked as you wish. Here we have ranked all the employees starting with lowest salary in a department. Now if we select rows with rn =1 then it will select employees from a department with lowest salary.
Then joined the result with department table to get the name of the
With lowestEarningEmployees as
(
id, first_name, last_name, department_id, salary, rank()over(partition by department_id order by salary)rn from employees
)
select le.id, le.first_name, le.last_name, le.department_id,d.name, le.salary,
from lowestEarningEmployees le inner join departments d on le.department_id=d.department_id
** If more than one employee in a department have lowest salary all of them will be selected. If you want to select only one employee with lowest salary then you need to use row_number() instead of rank().
You can also use subquery to have your desired result (Though I would suggest to use first one) :
Select e.id, e.first_name, e.last_name, e.department_id, d.name, e.salary
from employees e inner join department d on e.department_id = d.department_id
where e.salary=(select min(salary) from employees empl where e.department_id=empl.department_id)
Having two tables
Employee
Id
Name
Salary
DepartmentId
and
Departament
Id
Name
How can I get the highest average salary within two tables
like
Joe and Max belong to dept 1 so, avg is (70K+90K)/2
= 80K
and
Henry and Sam belog to dept 2, avg is (80K + 60K)/2=70k
so How to select the greatest avg salary by depto?, in this case
IT 80K
i have been trying:
'group the salary by each department and use the Max function to obtain the highest one.
select
Department.Name as Department,
T.M as Salary
from
Employee,
Department,
(select DepartmentId as ID, Max(Salary) as M from Employee group by DepartmentId) as T
where
Employee.Salary = T.M and
Department.Id = T.ID and
Employee.DepartmentId = Department.Id
enter image description here
If multiple department having same maximum avg salary then this solution will return multiple rows.
SELECT *
FROM(
SELECT d.Id, d.Name, AVG(e.Salary) avg_salary, RANK() OVER(ORDER BY AVG(e.Salary) DESC) AS rank_
FROM Employee e
INNER JOIN Departament d ON e.DepartmentId = d.Id
GROUP BY d.Id, d.Name
)T
WHERE rank_ = 1
If you want to get the average just for the department, you can use in this way.
select DepartmentId as ID, de.name as Deptname, Avg(Salary) as M from Employee em1
join Department de on de.departmentID = em1.DepartmentId
group by DepartmentId, de.name
If you want employee name along with highest average then you can use this approach as well.
select
Deptname as Department,
e.Name as Employeename,
z.M as Salary
from
Employee e
join
( select DepartmentId,Deptname, M, row_number() (order by m desc) rownum from ( select DepartmentId as ID, de.name as Deptname, Avg(Salary) as M from Employee em1
join Department de on de.departmentID = em1.DepartmentId
group by DepartmentId, de.name) as T) z
on
e.DepartmentId = T.DepartmentId and z.rownum = 1
If you want a full answer, you should provide DDL, sample data and desired result.
If I understand you correctly, you are looking for something like:
SELECT DepartmentID, AVG(Salary) AS AverageSalaryForDept
FROM Employee
GROUP BY DepartmentID
ORDER BY AverageSalaryForDept DESC;
This will give you all the averages, ordered from the highest to the lowest. Now if you want just the top one, add a FETCH clause:
SELECT DepartmentID, AVG(Salary) AS AverageSalaryForDept
FROM Employee
GROUP BY DepartmentID
ORDER BY AverageSalaryForDept DESC
OFFSET 0 ROWS FETCH NEXT 1 ROW ONLY;
HTH
Schema for EMPLOYEE
(ID, EMPLOYEENAME, SALARY, ORGANIZATIONID)
Query to Solve: Find employee Names in each organization with Maximum Salary without a Join.
SELECT E.*
FROM EMPLOYEE E,
(SELECT EMP.ORGANIZATIONID, MAX(EMP.SALARY)
FROM EMPLOYEE EMP
GROUP BY EMP.ORGANIZATIONID) MAXSALARY
WHERE MAXSALARY.SALARY =E.SALARY
AND E.ORGANIZATIONID=EMP.ORGANIZATIONID ;
Is there a way to avoid the join? I am using Spark SQL API and joins cause an extra shuffle operation which is expensive. Is there a way to get the employee name while getting the max salary?
Assume you have a single employee in each organization having the max salary
You can use PARTITION BY with Spark SQL as shown below (Although it will require a subquery)
SELECT E.*
FROM
(SELECT EMP.EMPLOYEENAME, EMP.ORGANIZATIONID, EMP.SALARY,
row_number() OVER (PARTITION BY ORGANIZATIONID ORDER BY SALARY DESC) as rank
FROM EMPLOYEE EMP
) AS E
WHERE E.rank=1
Try this:
SELECT P.ORGANIZATIONID, P.EMPLOYEENAME
FROM EMPLOYEE P
WHERE P.SALARY = (SELECT MAX(E.SALARY) FROM EMPLOYEE E WHERE P.ORGANIZATIONID = E.ORGANIZATIONID)
GROUP BY P.ORGANIZATIONID, P.EMPLOYEENAME
Try this:
SELECT EMPLOYEENAME FROM EMPLOYEE
WHERE SALARY IN (SELECT MAX(SALARY) FROM EMPLOYEE GROUP BY ORGANIZATIONID)
How can I get id of department in which employees receive the maximum salary:
Employee table: Empl (ID, FirstName, LastName, Salary, DeptId)
Departments table: Dept (ID, City)
rus (Вывести “id” подразделения, в котором сотрудники получают максимальную заработную плату.)
EDIT: Changed SUM(Salary) to AVG(Salary) based on comments on the question.
SELECT TOP 1 DeptId
FROM Employees
GROUP BY DeptId
ORDER BY AVG(Salary) DESC
SELECT TOP 1 B.*
FROM (SELECT DeptId, AVG(Salary) AvgSalary
FROM Empl
GROUP BY DeptId) A
INNER JOIN Dept B
ON A.DeptId = B.Id
ORDER BY AvgSalary DESC
To get the one single Department's ID where the highest single salary is paid:
SELECT TOP 1 DeptID
FROM dbo.Empl
ORDER BY Salary DESC
Or are you looking for something else?
I would assume you mean max average salary of a department and not the single highest salary across all departments.
However it seems all you would have to do is use the following SQL functions
MAX function
AVG function
group by department ID and viola.
Thought I agree with the comments above, I will assume you are doing this for research ;-)
select id
from dept
where id = ( select deptid
from ( select max(avg_salary), deptid
from ( select deptid, avg(salary) as avg_salary
from empl
group by deptid )
group by deptid )
)
:-)
SELECT DepartmentId
FROM Employee
WHERE Salary = (SELECT MAX(Salary) FROM Employee)