LeetCode数据库篇|181超过经理收入的员工
16lz
2021-01-22
大家好,从今天起我们将对Leetcode中数据库相关题目进行讲解,如果对SQL相关操作还不是很了解的读者可以点击万字Mysql学习笔记复习。
02
03
通过做题来学习是最有效的方式,阅读的同时一定要思考每种解法的异同,最好能够敲一遍。
本文为第181题:超过经理收入的员工
01
题目与SQL架构
Create table If Not Exists Employee (Id int, Name varchar(255), Salary int, ManagerId int);
Truncate table Employee;
insert into Employee (Id, Name, Salary, ManagerId) values ('1', 'Joe', '70000', '3');
insert into Employee (Id, Name, Salary, ManagerId) values ('2', 'Henry', '80000', '4');
insert into Employee (Id, Name, Salary, ManagerId) values ('3', 'Sam', '60000', 'None');
insert into Employee (Id, Name, Salary, ManagerId) values ('4', 'Max', '90000', 'None');
XX和XX比的基本思想是将比较的二者放在同一行
限制条件有两个:
员工的ManagerId是经理的Id
员工的Salary超过对于经理的Salary
02
第一种解法
基于笛卡尔积的连表
解法很直接,实际上就是自连接,从自己分为两个表以后用WHERE将两个限制条件表述出来,注意这里两表相连是笛卡尔积。
如果数据量大时需要优化
SELECT a.Name AS Employee
FROM Employee AS a,Employee AS b
WHERE a.ManagerId = b.Id
AND a.Salary > b.Salary
03
第二种解法
基于JOIN
的连表
这里使用LEFT JOIN根据Id和ManagerId完成自连接,再用salary判别即可。效率会超过笛卡尔积连表
SELECT a.name as Employee
FROM Employee a
LEFT JOIN Employee b ON a.ManagerId = b.id
WHERE a.salary > b.salary
04
第三种解法
基于WHERE
里的半连接
半连接的特点是建立的子查询是动态的,需要利用查询外部的条件。SQL的运算是逐行匹配,每次运行都将当前行的ManagerId传入子查询再和Salary用WHERE比对大小即可
SELECT Name Employee
FROM Employee E
WHERE Salary >
(
SELECT Salary FROM Employee WHERE Id = E.ManagerId
)
半连接思路很巧妙,可以巧妙化解分组聚合问题,但要注意:能连表则尽量不要用子查询,因为效率一般不高。