Search code examples
mysqlsqlsubquerycorrelated-subquery

Multiple results on outer query of correlated subquery


I was wondering if it is possible to have the inner query return multiple results that are then queried by the outer query?

Here is a reproducible example:

In this example, I'd like to know the name and salary of the highest paid employee of each department.

CREATE TABLE Worker (
    WORKER_ID INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    FIRST_NAME CHAR(25),
    LAST_NAME CHAR(25),
    SALARY INT(15),
    JOINING_DATE DATETIME,
    DEPARTMENT CHAR(25)
);

INSERT INTO Worker 
    (WORKER_ID, FIRST_NAME, LAST_NAME, SALARY, JOINING_DATE, DEPARTMENT) VALUES
        (001, 'Monika', 'Arora', 100000, '14-02-20 09.00.00', 'HR'),
        (002, 'Niharika', 'Verma', 80000, '14-06-11 09.00.00', 'Admin'),
        (003, 'Vishal', 'Singhal', 300000, '14-02-20 09.00.00', 'HR'),
        (004, 'Amitabh', 'Singh', 500000, '14-02-20 09.00.00', 'Admin'),
        (005, 'Vivek', 'Bhati', 500000, '14-06-11 09.00.00', 'Admin'),
        (006, 'Vipul', 'Diwan', 200000, '14-06-11 09.00.00', 'Account'),
        (007, 'Satish', 'Kumar', 75000, '14-01-20 09.00.00', 'Account'),
        (008, 'Geetika', 'Chauhan', 90000, '14-04-11 09.00.00', 'Admin');


Finding the highest salary of each department is easy enough:

SELECT MAX(SALARY), DEPARTMENT
FROM Worker
GROUP BY DEPARTMENT;

But how do I also add the names of the employees who earn these salaries to the results?

Many thanks!


Solution

  • You can use your query with the operator IN:

    SELECT * FROM Worker
    WHERE (DEPARTMENT, SALARY) IN (
      SELECT DEPARTMENT, MAX(SALARY) 
      FROM Worker
      GROUP BY DEPARTMENT 
    );
    

    or if you are using MySql 8.0+ with RANK() window function:

    SELECT w.* 
    FROM (
      SELECT *, RANK() OVER (PARTITION BY DEPARTMENT ORDER BY SALARY DESC) rnk
      FROM Worker
    ) w
    WHERE w.rnk = 1
    

    See the demo.
    Results:

    > WORKER_ID | FIRST_NAME | LAST_NAME | SALARY | JOINING_DATE        | DEPARTMENT
    > --------: | :--------- | :-------- | -----: | :------------------ | :---------
    >         3 | Vishal     | Singhal   | 300000 | 2014-02-20 09:00:00 | HR        
    >         4 | Amitabh    | Singh     | 500000 | 2014-02-20 09:00:00 | Admin     
    >         5 | Vivek      | Bhati     | 500000 | 2014-06-11 09:00:00 | Admin     
    >         6 | Vipul      | Diwan     | 200000 | 2014-06-11 09:00:00 | Account