I just started studying SQL queries.
I am practicing on this site: https://www.techonthenet.com/sql/joins_try_sql.php
I want to find:
"the name of the employee with the highest salary for every department".
My query is:
SELECT first_name, max(salary) FROM employees, departments
WHERE departments.dept_id=employees.dept_id
GROUP BY employees.dept_id
And I get null value for first_name :
I understand that the problem is due to the group by expressions. But how can I solve this?
Tables:
You can alternatively use row_number() like below, you don't need to join to departments table unless you need to show the name of the department:
Select e.*
from employees e
INNER JOIN
(
SELECT e.id, e.dept_id. e.first_name,
rn=row_number() over (partition by e.dept_id order by e.salary desc)
FROM employees e
) x ON x.id = e.id
where x.rn = 1
EDIT
(Since OP does not want to use row_number() function amd it turned out the query will be used in mysql instead of sql server) -> Can you please try this:
select em.*
from employees em, (
Select dept_id, max(salary) salary
from employees e
group by dept_id
) x on x.dept_id=em.dept_id and x.salary = em.salary
That should work but the online compiler does not accept join with a sub-query as far as I understand. Easiest solution I can think of, in this case:
select em.*
from employees em
where salary = (select max(salary) from employees em2 where em.dept_id = em2.dept_id)
SELECT top 2 first_name,max(salary) FROM employees, departments
WHERE departments.dept_id=employees.dept_id
GROUP BY first_name
order by max(salary) desc
try this:
SELECT e.first_name, e.salary FROM employees as e
INNER JOIN departments as d ON d.dept_id=e.dept_id
WHERE e.salary IN (SELECT max(salary) FROM employees GROUP BY dept_id)
Try this:
select first_name, b.dept_id, salary from employees a,
(
SELECT employees.dept_id, max(salary) as salary FROM employees, departments
WHERE departments.dept_id=employees.dept_id
GROUP BY employees.dept_id
)b where a.salary = b.salary and a.dept_id= b.dept_id
Related
I want to print name and salary amount of the employee which has highest salary, till now its okay but if there are multiple records than print all. There are two table given :-
EMPLOYEE TABLE :-
SALARY TABLE:-
my query is: -
SELECT E.NAME, S.AMOUNT
FROM `salary` S,
employee E
WHERE S.EMPLOYEE_ID = E.ID
and S.AMOUNT = (SELECT max(`AMOUNT`)
FROM `salary`)
is there any better way to find out the solution ?
It is "with ties" functionality what you're trying to achieve. Unfortunately mySQL doesn't support that (in the docs there is nothing to add to the "LIMIT" part of the query), so you have no other option rather than looking for max salary first and filter records afterwards.
So, your solution is fine for that case.
Alternatively, if you're on version 8 and newer, you may move the subquery to the with clause
with max_sal as (
select max(amount) ms from salary
)
SELECT E.NAME, S.AMOUNT
FROM salary S
JOIN employee E
ON S.EMPLOYEE_ID = E.ID
JOIN max_sal ms
ON S.AMOUNT = ms.ms
or search for it in the join directly
SELECT E.NAME, S.AMOUNT
FROM salary S
JOIN employee E
ON S.EMPLOYEE_ID = E.ID
JOIN (select max(amount) ms from salary) ms
ON S.AMOUNT = ms.ms
But I'm sure it won't get you any better performance
I like solving them with a join:
WITH M as (select max(amount) as amount from salary)
SELECT E.NAME, S.AMOUNT
FROM M JOIN SALARY USING(AMOUNT) JOIN Employee USING(Id)
but your solution is perfectly fine..
I would like to find the difference between the average salary of the pilots and the average salary of the employees, including pilots, so basically a (average(pilot) - average(employees)).
Though I'm having trouble combining the two SQL queries together, here's what I've managed to do so far:
SELECT AVG(salary) AS 'average(pilot)'
FROM employees e, certified c
WHERE e.EID IN (SELECT EID FROM certified GROUP BY eid);
SELECT AVG(salary) AS 'average(employees)'
FROM employees e, certified c
WHERE e.EID NOT IN (SELECT EID FROM certified GROUP BY eid);
Now I only need to subtract the result of the second query from the first query. How do I proceed?
select (select query2) - (select query1);
I guess this should work,
select (select avg(salary) as 'average(employees)'
from employees e, certified c
where e.EID not in (select EID from certified group by eid)) - (select avg(salary) as 'average(pilot)'
from employees e, certified c
where e.EID in (select EID from certified group by eid));
Refer this for similar answers
You can find the problem from here.
When there are multiple people with the highest salary in each department, the following SQL command output the expected results - all employees with highest salary are output:
select d.Name as Department, e.Name as Employee, e.Salary as Salary
from
(select Name, Salary, DepartmentId
from Employee
having (Salary, DepartmentId) in (
select max(Salary), DepartmentId
from Employee
group by DepartmentId)
)e, Department d
where e.DepartmentId = d.Id
However, the following command only output one employee even if there are multiple employees with the same highest salary:
select d.Name as Department, e.Name as Employee, e.Salary as Salary
from
(select Name, Salary, DepartmentId
from Employee
group by DepartmentId
having Salary = max(Salary)
)e, Department d
where e.DepartmentId = d.Id
Can anyone explain to me why the latter one does not work? Thanks!
The reason the second query doesn't work is because it's getting the max salary regardless of the department.
The way I would have done this, despite the valid first query (which is not using the standard JOIN syntax like it should), would be to first get the highest salary for each department like this:
SELECT departmentID, MAX(salary)
FROM employee
GROUP BY departmentID;
Once you have that, you can use a self join to only select the rows with that salary and department. This will include multiple people if they have the same salary:
SELECT e.*
FROM employee e
JOIN(
SELECT departmentID, MAX(salary) AS maxSalary
FROM employee
GROUP BY departmentID) tmp ON tmp.departmentID = e.departmentID AND tmp.maxSalary = e.salary
For further explanation, consider just the inner subquery you have:
SELECT name, department, salary
FROM employee
GROUP BY department
HAVING salary = MAX(salary);
The first problem with this is that you are selecting rows that are not consistent within your group. For each department id, you have multiple name values and multiple salary values, which will be chosen arbitrarily when you do the grouping. In my example, and the first, you can see that the grouping explicitly pulls the (departmentID, salary) pair for the max salary in each department, which the second one does not.
Here is an SQL Fiddle example to visually see the differences between your second query and mine.
I need to display the department name and the number of employees of the department with more employees.
However I am receiving the following error (#1111 - Invalid use of group function). Here's the query:
select e.dept_no, dnombre, count(*) from emple e, depart d
where e.dept_no=d.dept_no
group by e.dept_no, dnombre
having count(*)=(select max(count(*)) from emple group by dept_no);
I need help with this query in MySQL.
Instead of Nesting aggregates use Limit to get the max count. Try this..
select e.dept_no, dnombre, count(*) from emple e, depart d
where e.dept_no=d.dept_no
group by e.dept_no, dnombre
having count(*)=(select count(*) from emple group by dept_no order by count(*) Desc limit 1);
Used a left join in case all departments had no employees which is not handled in this set due to an inner join.
used a group by on d.dept_no since e.dept number could be null.
ordered by count of d.depts dec
used a limit operator to only return "ONE" max record. Note, this approach will not show ties..
.
SELECT count(d.dept), d.dnombre, d.dept_no
FROM Emple e
LEFT JOIN depart d
on E.dept_no=d.dept_no
GROUP BY d.dept_no, d.dnombre
ORDER BY count(d.dept) desc
LIMIT 1;
if you want to use the MAX function you can also do it like this:
SELECT e.dept_no, dnombre, COUNT(*)
FROM emple e, depart d
WHERE e.dept_no=d.dept_no
GROUP BY e.dept_no, dnombre
HAVING COUNT(*) = (SELECT MAX(cnt) FROM (SELECT COUNT(*) AS cnt FROM emple GROUP BY dept_no) T);
I have a problem with extracting data from db. My code looks like:
SELECT MAX(maximum)as Number FROM
(
SELECT department_name, COUNT(employees.employee_id) AS maximum
FROM departments, employees
WHERE departments.department_id=employees.department_id
GROUP BY department_name
)t
and the result is:
Number
1 46
and this is the number of maximum employees in one of the departments.
The problem is that i want to have additional column with the name of the department in wich there is 46 employees. I tried something like:
select department_name, count(employees.employee_id)
from departments, employees
where departments.department_id=employees.department_id
group by department_name
having count(employees.employee_id) =
( SELECT MAX(maxx)FROM
(SELECT department_name, COUNT(employees.employee_id) AS maxx
FROM departments, employees
WHERE departments.department_id=employees.department_id
GROUP BY department_name
);
but it doesn't work. Please help!
try this
SELECT t.department_name, MAX(t.maximum) as Number FROM (
SELECT
department_name,
COUNT(employees.employee_id) AS maximum
FROM departments, employees
WHERE departments.department_id=employees.department_id
GROUP BY department_name
) t
How about this just order your results by maximum in descending order with limit 1,also use modern join syntax query
SELECT d.department_name,
COUNT(e.employee_id) AS maximum
FROM departments d
LEFT JOIN employees e
ON (d.department_id=e.department_id)
GROUP BY d.department_name
ORDER BY maximum DESC
LIMIT 1
This will give you the department name who has the highest count of employees
You could also tack on an additional JOIN to the first query you posted as such:
SELECT TOP 1 d.department_name, MAX(maximum) as Number FROM
(
SELECT department_id AS department_id, COUNT(employees.employee_id) AS maximum
FROM departments, employees
WHERE departments.department_id=employees.department_id
GROUP BY department_id
)t
JOIN departments d ON d.department_id = t.department_id
GROUP BY d.department_name
ORDER BY Number DESC
I tried this with a similar data model in my domain and it works quite nicely.