一、題目名稱算法
Department Top Three Salaries(各部門工資最高的三我的)sql
二、題目地址數據庫
https://leetcode.com/problems/department-top-three-salaries/工具
三、題目內容命令行
表Employee保存了全部僱員的數據,每名僱員都有一個Id,和一個部門Id(DepartmentId)code
+----+-------+--------+--------------+ | Id | Name | Salary | DepartmentId | +----+-------+--------+--------------+ | 1 | Joe | 70000 | 1 | | 2 | Henry | 80000 | 2 | | 3 | Sam | 60000 | 2 | | 4 | Max | 90000 | 1 | | 5 | Janet | 69000 | 1 | | 6 | Randy | 85000 | 1 | +----+-------+--------+--------------+
表Department保存了每一個部門的Id和名稱three
+----+----------+ | Id | Name | +----+----------+ | 1 | IT | | 2 | Sales | +----+----------+
現須要寫一個SQL,找出每一個部門工資最高的三名僱員。例如以上面的兩張表的數據,查詢出的結果集應該是這樣的:leetcode
+------------+----------+--------+ | Department | Employee | Salary | +------------+----------+--------+ | IT | Max | 90000 | | IT | Randy | 85000 | | IT | Joe | 70000 | | Sales | Henry | 80000 | | Sales | Sam | 60000 | +------------+----------+--------+
四、初始化數據庫腳本get
在MySQL數據庫中創建一個名爲LEETCODE的數據庫,用MySQL命令行中的source命令執行下面腳本:class
-- 執行腳本前必須創建名爲LEETCODE的DATABASE USE LEETCODE; DROP TABLE IF EXISTS Employee; CREATE TABLE Employee ( Id INT NOT NULL PRIMARY KEY, Name VARCHAR(10), Salary INT, DepartmentId INT ); INSERT INTO Employee (Id, Name, Salary, DepartmentId) VALUES (1, 'JID', 70000, 1); INSERT INTO Employee (Id, Name, Salary, DepartmentId) VALUES (2, 'KAT', 80000, 2); INSERT INTO Employee (Id, Name, Salary, DepartmentId) VALUES (3, 'FCK', 60000, 2); INSERT INTO Employee (Id, Name, Salary, DepartmentId) VALUES (4, 'DIR', 90000, 1); INSERT INTO Employee (Id, Name, Salary, DepartmentId) VALUES (5, 'CAT', 69000, 1); INSERT INTO Employee (Id, Name, Salary, DepartmentId) VALUES (6, 'DOT', 85000, 1); INSERT INTO Employee (Id, Name, Salary, DepartmentId) VALUES (7, 'GOS', 25000, 1); INSERT INTO Employee (Id, Name, Salary, DepartmentId) VALUES (8, 'OPA', 90000, 2); INSERT INTO Employee (Id, Name, Salary, DepartmentId) VALUES (9, 'OPB', 30000, 2); INSERT INTO Employee (Id, Name, Salary, DepartmentId) VALUES (10, 'DIK', 30000, 3); INSERT INTO Employee (Id, Name, Salary, DepartmentId) VALUES (11, 'POD', 30000, 3); INSERT INTO Employee (Id, Name, Salary, DepartmentId) VALUES (12, 'SUV', 30000, 3); INSERT INTO Employee (Id, Name, Salary, DepartmentId) VALUES (13, 'ABC', 30000, 3); INSERT INTO Employee (Id, Name, Salary, DepartmentId) VALUES (15, 'WKK', 75000, 4); INSERT INTO Employee (Id, Name, Salary, DepartmentId) VALUES (16, 'JYY', 60000, 4); INSERT INTO Employee (Id, Name, Salary, DepartmentId) VALUES (17, 'XWY', 60000, 4); INSERT INTO Employee (Id, Name, Salary, DepartmentId) VALUES (18, 'KMT', 55000, 4); INSERT INTO Employee (Id, Name, Salary, DepartmentId) VALUES (14, 'LXK', 90000, 999); DROP TABLE IF EXISTS Department; CREATE TABLE Department ( Id INT NOT NULL PRIMARY KEY, Name VARCHAR(10) ); INSERT INTO Department (Id, Name) VALUES (1, 'DPRT1'); INSERT INTO Department (Id, Name) VALUES (2, 'DPRT2'); INSERT INTO Department (Id, Name) VALUES (3, 'DPRT3'); INSERT INTO Department (Id, Name) VALUES (4, 'DPRT4');
五、解題SQL
先寫一個SQL,查詢出每一個有部門的人的部門和工資
SELECT D.NAME Dep, E.NAME Emp, E.Salary Sal FROM Employee E LEFT JOIN Department D ON E.DepartmentId = D.Id WHERE D.NAME IS NOT NULL
使用 MySQL Query Browser 工具查詢結果以下:
根據這個SQL,能夠繼續寫出一個查詢出每一個部門工資處於前三名位置的員工列表:
SELECT A.Dep Department, A.Emp Employee, A.Sal Salary FROM (SELECT D.NAME Dep, E.NAME Emp, E.Salary Sal FROM Employee E LEFT JOIN Department D ON E.DepartmentId = D.Id WHERE D.NAME IS NOT NULL) A WHERE (SELECT COUNT(*) FROM (SELECT D.NAME Dep, E.NAME Emp, E.Salary Sal FROM Employee E LEFT JOIN Department D ON E.DepartmentId = D.Id WHERE D.NAME IS NOT NULL) B WHERE A.Dep = B.Dep AND A.Sal < B.Sal) < 3 ORDER BY A.Dep ASC, A.Sal DESC
這個SQL的查詢結果集以下:
能夠看到,部門4(DPRT4)有四我的,一個高工資(WKK,75000),一個低工資(KMT,55000),其餘兩我的工資(JYY,XWY,60000)是同樣的。按照上面的SQL,會查出該部門工資最高的三我的是WKK、JYY、XWY,我認爲這是一種合理的結果,即:
查出每一個部門工資排名最靠前的三我的,若有多於三人工資並列第一則將這些人都查出,若有多於兩人工資並列第二則查出排名第一的人和這些並列第二的人,若有多於一人工資並列第三則查出排名第1、二名的人和全部並列第三名的人。
但這種相似計算長跑比賽前三名的算法卻並非本題的「正確答案」,本題實際上要咱們找的並非要你求出每一個部門工資最高的三我的,而是要:
先求出每一個部門第三高的工資,再求出該部門工資數不小於第三高工資的全部僱員。
雖然我認爲這是不合理的答案,不過仍是寫了一個「正確」的SQL以下:
SELECT A.Dep Department, A.Emp Employee, A.Sal Salary FROM (SELECT D.NAME Dep, E.NAME Emp, E.Salary Sal FROM Employee E LEFT JOIN Department D ON E.DepartmentId = D.Id WHERE D.NAME IS NOT NULL) A WHERE (SELECT COUNT(DISTINCT Sal) FROM (SELECT D.NAME Dep, E.NAME Emp, E.Salary Sal FROM Employee E LEFT JOIN Department D ON E.DepartmentId = D.Id WHERE D.NAME IS NOT NULL) B WHERE A.Dep = B.Dep AND A.Sal < B.Sal) < 3 ORDER BY A.Dep ASC, A.Sal DESC
查詢出的結果集以下:
另外一種更簡單的SQL寫法以下,查詢結果集與上同:
SELECT D.NAME Department, E.NAME Employee, E.Salary Salary FROM Department D, Employee E WHERE E.DepartmentId = D.Id AND (SELECT COUNT(DISTINCT Salary) FROM Employee WHERE DepartmentId = D.Id AND Salary > E.Salary) < 3
END