I have employee and department tables.
I need to find the following SQL query:
What is the employee with the lowest salary for each department where the employees salary is greater than the average salary for the department.
I tried this:
select * from [Company Management].[dbo].[Employee]
where Salary in
(select min(Salary) from [Company Management].[dbo].[Employee]
where salary>=All
--average employee salary for department
(select avg(salary) from [Company Management].[dbo].[Employee]
group by DepartmentID)
group by DepartmentID)
What I get in the result is greater than both averages and not department specific.
i.e. if the average for department 1 is 50 and for department 2 is 37 I get correct answer for department 1 but 75 for department two, and department 2 has an employee with 40.
Select avarage salaries per department in employees.
Join with employees and find thus the minimum salary higer than the avarage salary per department.
Join again with employees to get all employees having that salary in their department.
Here is the statement:
select employee.*
from employee
join
(
select employee.departmentid, min(employee.salary) as sal
from employee
join
(
select departmentid, avg(salary)
from employee
group by departmentid
) avg_sals on avg_sals.departmentid = employee.departmentid and avg_sals.salary < employee.salary
group by employee.departmentid
) wanted_sals on wanted_sals.departmentid = employee.departmentid and wanted_sals.sal = employee.salary;
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 have a SQL server problem where i have to get the average of the maximum salaries in each department. For example I have a department with id 1 that has an employee with a maximum salary of 50000, and a department with id 2 that has an employee with a maximum salary of 30000, what i have to do is calculate the average between these 2.
What I tried:
SELECT AVG(MAX(salary))
FROM employees
GROUP BY department_id
most simple think you can do is (if in the employee table, you have a department_id) :
SELECT AVG(p.maximum)
FROM (SELECT department_id, MAX(salary) AS maximum
FROM employees
GROUP BY department_id) p
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
I have to create a report which displays the highest salaries in each department.
I must have the following columns, department_id, department_name, last_name and MAX(salary). And it cannot contain any duplicates.
I have managed to get a query result with all the columns however due to the last_name column I have a query result as the following.
90, Executive, De Haan, 17000
90, Executive, Kochhar, 17000
80, Sales, Tucker, 10000
80, Sales, Bernstein, 9500
80, Sales, Hall, 9000
Obviously, the highest in the Executive department is 17000, and 10000 in Sales. I need to display only 1 salary amount for each department. Any ideas on how I achieve this?
Below is what I typed into SQL to get this result.
SELECT DISTINCT department_id, department_name, last_name, MAX(salary)
FROM employees
NATURAL JOIN departments
GROUP BY department_id, department_name, last_name
ORDER BY MAX(salary) DESC;
So you need to find the max salary per department id then join back to the employee table to pull the last name. Something like this:
SELECT sub.department_id, sub.department_name, emp.last_name, sub.max_sal
FROM
(SELECT e.department_id, d.department_name, MAX(e.salary) AS max_sal
FROM employees e
INNER JOIN departments d
ON e.department_id = d.department_id
GROUP BY e.department_id, d.department_name) sub
INNER JOIN employees emp
ON sub.department_id = emp.department_id
AND sub.max_sal = emp.salary
Note that this solution would show multiple people if they have the same salary and it's the highest for their department.