Calculate the highest salary for each department - sql

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.

Related

Query to display employees with lowest salary from each department

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)

employee department wise and count of employees more than 5

i want to display department_id's along with count,and count should be more than 5, and i want to have employees who are not hired in January.
i tried the below query
SELECT * FROM EMPLOYEES
WHERE DEPARTMENT_ID IN
(
SELECT DEPARTMENT_ID
FROM EMPLOYEES
GROUP BY DEPARTMENT_ID
HAVING COUNT(*)>5
)
AND HIRE_DATE NOT LIKE '%JAN%';
but here I didnt get count.I want count Also.
SELECT department_ID, count(employee_id) as '# of Employees' FROM EMPLOYEES
WHERE DEPARTMENT_ID IN
(
SELECT DEPARTMENT_ID
FROM EMPLOYEES
GROUP BY DEPARTMENT_ID
HAVING COUNT(*)>5
)
AND HIRE_DATE NOT LIKE '%JAN%'
group by department_ID;
This query returns the department_id and because I group by department_id, the count of employees that belong to each department will be returned
Output will look something like this
Department_Id | # of Employees
1 7
2 6
4 9
If you want the dept id and count of employees (where employee hire date is not in Jan) then something like the following should work. I say "something like the following" because I suspect the WHERE hire_date NOT LIKE '%JAN%' could be improved, but it would just depend on the format of that column.
SELECT
DEPARTMENT_ID,
COUNT(*)
FROM EMPLOYEES
WHERE HIRE_DATE NOT LIKE '%JAN%'
GROUP BY DEPARTMENT_ID
HAVING COUNT(*)>5;
If you also want to list the individual employees along with these departments, then something like this might work:
SELECT a.*, b.count(*)
FROM EMPLOYEES AS a
INNER JOIN (
SELECT
DEPARTMENT_ID,
COUNT(*)
FROM EMPLOYEES
WHERE HIRE_DATE NOT LIKE '%JAN%'
GROUP BY DEPARTMENT_ID
HAVING COUNT(*)>5) AS b
ON a.department_id = b.department_id
WHERE a.HIRE_DATE NOT LIKE '%JAN%';
Again, though, I think you can leverage your schema to improve the where clause on HIRE_DATE. A like/not-like clause is generally going to be pretty slow.
Select the count from your inner query and join to it:
SELECT E.*, DEPT_COUNT
FROM EMPLOYEES E
JOIN (
SELECT DEPARTMENT_ID, COUNT(*) DEPT_COUNT
FROM EMPLOYEES
GROUP BY DEPARTMENT_ID
HAVING COUNT(*) > 5
) DC ON E.DEPARTMENT_ID = DC.DEPARTMENT_ID
AND HIRE_DATE NOT LIKE '%JAN%'

Display salary, Avg(salary), Name for those who earns more than company Avg(salary)

how to display the name, salary and the avg(salary) for all the employees whose salary is greater than the company avg(salary).
I have tried the following query:
Select last_name, salary
From employees
Where salary >(select avg(salary) from employees);
This gives the names of those employees who are getting higher salary than the company avg(salary). But I want to display the avg(salary) in the select list aswell.
Join the employee table to a query that produces the average:
select last_name, salary, avg_salary
from employees
join (select avg(salary) avg_salary from employees) x
on salary > avg_salary
This query will work on all databases.
Assuming sql server, here is but one of many ways to accomplish this:
DECLARE #AverageSalary MONEY
SELECT #AverageSalary=AVG(SALARY) FROM EMPLOYEES
Select last_name, salary, #AverageSalary From employees Where salary > #AverageSalary

Sql query unsuccessful

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;

ORA-00934: Group function not allowed here || Selecting MIN(Salary) of highest paid dept

O community, do you know how I could select the department_ID, and lowest salary of the department with the highest average salary? Or how to eliminate the'ORA-00934: group function not allowed here' issue? Would I need to use two subqueries?
So far, this is what I've come up with, trying to get the department_ID of the highest paid department:
SELECT department_ID, MIN(salary
FROM employees
WHERE department_ID = (SELECT department_ID
FROM employees WHERE salary = MAX(salary));
Thank you, your assistance is greatly appreciated.
I can't test this, but it should work:
;WITH DepartmentsSalary AS
(
SELECT department_ID, AVG(Salary) AvgSalary, MIN(Salary) MinSalary
FROM employees
GROUP BY department_ID
)
SELECT department_ID, MinSalary
FROM ( SELECT department_ID, AvgSalary, MAX(AvgSalary) OVER() MaxSalary, MinSalary
FROM DepartmentsSalary) D
WHERE MaxSalary = AvgSalary
You can use join (then you have just one sub query)
select e1.department_ID, min(e1.salary)
from employees e1
join (
select avg_query.department_ID, max(avg_query.avg_value)
from (
select department_ID, avg(salary) as avg_value
from employees
group by department_ID
) avg_query
) e2 on e2.department_ID = e1.department_ID
;
First sub-query returned average salary for all departments
Next sub-query based on first sub-query returned highest average
salary and related department_ID
Main query returned min salary for department_ID with highest average
salary