#181. 超过经理收入的员工

https://leetcode-cn.com/problems/employees-earning-more-than-their-managers/

  1. +-------------+---------+
  2. | Column Name | Type |
  3. +-------------+---------+
  4. | id | int |
  5. | name | varchar |
  6. | salary | int |
  7. | managerId | int |
  8. +-------------+---------+
  9. Id是该表的主键。
  10. 该表的每一行都表示雇员的ID、姓名、工资和经理的ID

编写一个SQL查询来查找收入比经理高的员工。
任意顺序 返回结果表。

SELECT a.name AS Employee
FROM Employee AS a JOIN Employee AS b
ON a.managerId = b.id
WHERE a.salary > b.salary
SELECT a.name Employee 
FROM 
(
    SELECT e1.name, e1.salary, e1.managerId, e2.salary m_salary
    FROM Employee e1
    LEFT JOIN Employee e2
    ON e1.managerId = e2.id
) a
WHERE a.salary>a.m_salary

#182. 查找重复的电子邮箱

https://leetcode-cn.com/problems/duplicate-emails/

编写一个 SQL 查询,查找 Person 表中所有重复的电子邮箱。

+----+---------+
| Id | Email   |
+----+---------+
| 1  | a@b.com |
| 2  | c@d.com |
| 3  | a@b.com |
+----+---------+

根据以上输入,你的查询应返回以下结果:

+---------+
| Email   |
+---------+
| a@b.com |
+---------+

说明:所有电子邮箱都是小写字母。

SELECT Email
FROM Person
GROUP BY Email
HAVING Count(Email)>1

#183. 从不订购的客户

https://leetcode-cn.com/problems/customers-who-never-order/
某网站包含两个表,Customers 表和 Orders 表。编写一个 SQL 查询,找出所有从不订购任何东西的客户。

+----+-------+
| Id | Name  |
+----+-------+
| 1  | Joe   |
| 2  | Henry |
| 3  | Sam   |
| 4  | Max   |
+----+-------+
+----+------------+
| Id | CustomerId |
+----+------------+
| 1  | 3          |
| 2  | 1          |
+----+------------+

例如给定上述表格,你的查询应返回:

+-----------+
| Customers |
+-----------+
| Henry     |
| Max       |
+-----------+
SELECT Name `Customers`
FROM
(
    SELECT c.Id, c.Name, o.ID OrderId
    FROM Customers c
    LEFT JOIN Orders o ON c.id=o.CustomerId
) a
WHERE OrderId IS NULL

#184. 部门工资最高的员工

https://leetcode-cn.com/problems/department-highest-salary/

+--------------+---------+
| 列名          | 类型    |
+--------------+---------+
| id           | int     |
| name         | varchar |
| salary       | int     |
| departmentId | int     |
+--------------+---------+
id是此表的主键列。
departmentId是Department表中ID的外键。
此表的每一行都表示员工的ID、姓名和工资。它还包含他们所在部门的ID。
+-------------+---------+
| 列名         | 类型    |
+-------------+---------+
| id          | int     |
| name        | varchar |
+-------------+---------+
id是此表的主键列。
此表的每一行都表示一个部门的ID及其名称。

编写SQL查询以查找每个部门中薪资最高的员工。
任意顺序 返回结果表。

SELECT a.Dname Department, a.name Employee, a.salary Salary
FROM
(
    SELECT e.id, e.name, d.name Dname, e.salary, 
    DENSE_RANK() OVER(Partition By departmentId ORDER BY salary DESC) SRank
    FROM Employee e
    LEFT JOIN Department d
    ON e.departmentId=d.id
) a
WHERE SRank=1

#185. 部门工资前三高的所有员工

+--------------+---------+
| Column Name  | Type    |
+--------------+---------+
| id           | int     |
| name         | varchar |
| salary       | int     |
| departmentId | int     |
+--------------+---------+
Id是该表的主键列。
departmentId是Department表中ID的外键。
该表的每一行都表示员工的ID、姓名和工资。它还包含了他们部门的ID。
+-------------+---------+
| Column Name | Type    |
+-------------+---------+
| id          | int     |
| name        | varchar |
+-------------+---------+
Id是该表的主键列。
该表的每一行表示部门ID和部门名。

公司的主管们感兴趣的是公司每个部门中谁赚的钱最多。一个部门的 高收入者 是指一个员工的工资在该部门的 不同 工资中 排名前三 。

编写一个SQL查询,找出每个部门中 收入高的员工 。

以 任意顺序 返回结果表。

SELECT a.DName Department, a.name Employee, a.salary Salary
FROM
(
    SELECT e.id, e.name, e.salary, d.name DName,
    # 在这里我们要考虑一下使用 dense_rank() 还是 rank()
    # rank()会在重复值出现时跳过下一位
    # dense_rank()出现重复值时依然会保持连续的顺序
    # 显然,我们在这里用dense_rank()较为合适
    DENSE_RANK() OVER (Partition By departmentId ORDER BY salary DESC) SRank
    FROM Employee e
    LEFT JOIN Department d
    ON e.departmentId=d.id
) a
WHERE a.SRank<=3

今日知识点

  1. 复习了昨天的dense_rank()的使用
  2. 使用了Having 函数
  3. 复习了昨天的 Left Join
  4. dense_rank()中使用partition by来合并同类项