相信很多学习SQL的小伙伴都面临这样的困境,学习完书本上的SQL基础知识后,一方面想测试下自己的水平;另一方面想进一步提升,却不知道方法。
其实,对于技能型知识,我的观点一贯都是:多练习、多实践。正所谓实践出真知,学完书本的知识,很多时候也只能做到知道,距离熟练的应用还差的很远。
在咱们程序员圈子里,力扣(LeetCode)和牛客(nowcoder.com)是两个公认比较好的实践平台。题库比较多,还有不少大厂的笔试真题,特别适合找工作时撸一撸。当然,作为平时个人技术提升的练习题,也是非常不错的。
最近一段时间,我会先从力扣(LeetCode)的SQL题刷起。当然,顺序可能是随机的,欢迎小伙伴们点题。
题目:1303. 求团队人数
员工表:Employee
+---------------+---------+
| Column Name | Type |
+---------------+---------+
| employee_id | int |
| team_id | int |
+---------------+---------+
employee_id 字段是这张表的主键,表中的每一行都包含每个员工的 ID 和他们所属的团队。
编写一个 SQL 查询,以求得每个员工所在团队的总人数。
查询结果中的顺序无特定要求。
查询结果格式示例如下:
Employee Table:
+-------------+------------+
| employee_id | team_id |
+-------------+------------+
| 1 | 8 |
| 2 | 8 |
| 3 | 8 |
| 4 | 7 |
| 5 | 9 |
| 6 | 9 |
+-------------+------------+
Result table:
+-------------+------------+
| employee_id | team_size |
+-------------+------------+
| 1 | 3 |
| 2 | 3 |
| 3 | 3 |
| 4 | 1 |
| 5 | 2 |
| 6 | 2 |
+-------------+------------+
ID 为 1、2、3 的员工是 team_id 为 8 的团队的成员,
ID 为 4 的员工是 team_id 为 7 的团队的成员,
ID 为 5、6 的员工是 team_id 为 9 的团队的成员。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/find-the-team-size
解题思路:
这道题用到的概念还蛮多的:自关联、笛卡尔积、聚合函数、子查询。
记得之前有个同事,一直理解不了自关联是什么意思。
其实,自关联就是自己跟自己关联。如果你也理解不了,不妨把自己叫做a表,再复制一个自己,叫做b表,然后a表与b表关联,这样就是两张不同的表关联,就好理解了。区别就是这两张表是一模一样的。
具体到这道题,因为来源表员工表的主键是employee_id,而结果的主键也是employee_id,并且是所有员工的数据都要有。那么说明源表与结果表的主键是一致的。
最简单的思路,就是直接查询Employee表,而且还不需要加条件。这样就能返回所有要求返回的员工记录。至于要求返回的第2个字段team_size,想办法inner join或者left join上去就可以了。
那么team_size怎么获取呢?直接使用group by对team_id分组,然后取每个分组内的员工数即可。
当然,这样就需要使用到子查询,先计算出每个team的team_size。
可不可以不使用子查询呢?
其实,对于team_size,也可以从每个员工的team_id出发,关联出这个team_id下所有的员工,然后使用employee_id做分组汇总,取出分组下的数据条数即可。
参考SQL:
#方法1
select
a.employee_id,
b.team_size
from employee a
inner join
(
select
team_id,
count(1) team_size
from employee
group by team_id
)b
on a.team_id = b.team_id;
#方法2
select
a.employee_id,
count(1) team_size
from employee a
inner join employee b
on a.team_id = b.team_id
group by a.employee_id