排序和分组
排序 (ORDER BY) 和分组 (GROUP BY) 常用于按照特定维度对数据块进行过滤和去重统计。
2356. 每位教师所教授的科目种类的数量 (Number of Unique Subjects Taught by Each Teacher)
题目描述
Teacher 表保存了教师教授科目和在哪个系教授的信息:
teacher_id: 教师 ID。subject_id: 科目 ID。dept_id: 系 ID。
请编写一个解决方案,计算每位老师在大学里教授的 不同 科目的数量。
解题思路
去重统计 + 分组。
GROUP BY teacher_id将教师进行分组。- 对每组中的
subject_id进行COUNT(DISTINCT ...)以排除同一个老师教多门相同科目的情况。
SQL 实现 (MySQL)
SELECT teacher_id, COUNT(DISTINCT subject_id) AS cnt
FROM Teacher
GROUP BY teacher_id;
1141. 查询近30天活跃用户数 (User Activity for the Past 30 Days I)
题目描述
Activity 表记录了社交媒体网站的用户活动:
user_id: 用户 ID。session_id: 会话 ID。activity_date: 活动日期。activity_type: 活动类型 ('open_session', 'end_session', 'scroll_down', 'send_message')。
请编写一个解决方案,找出截至 2019-07-27(包含当天)近 30 天内,每日活跃用户的数量(至少进行过一次活动的用户即为活跃用户)。
解题思路
日期范围过滤 + 分组计数。
- 时间窗口:
2019-07-27的前 30 天,即起始日期为2019-07-27 - 29,对应区间为[2019-06-28, 2019-07-27]。 - 聚合:关键在于
COUNT(DISTINCT user_id),因为一个用户会在同一天进行多次活动。
SQL 实现 (MySQL)
SELECT activity_date AS day, COUNT(DISTINCT user_id) AS active_users
FROM Activity
WHERE activity_date BETWEEN '2019-06-28' AND '2019-07-27'
GROUP BY activity_date;
1084. 销售分析 III (Sales Analysis III)
题目描述
你有两张表:
Product: 包含product_id(主键) 和product_name。Sales: 记录销售情况,包含product_id,buyer_id,sale_date,quantity,price。
请编写一个解决方案,报告 仅 在 2019 年第一季度(即 2019-01-01 至 2019-03-31)销售的产品。
解题思路
聚合条件筛选 (HAVING)。
- 将
Product表与Sales表关联。 GROUP BY product_id。- 条件:该产品销售记录中的 最小值日期 和 最大值日期 必须全部处于第一季度范围内。如果最小日期小于一月或最大日期大于三月,则说明在其他季度也有销售,不符合“仅”的要求。
SQL 实现 (MySQL)
SELECT product_id, product_name
FROM Sales JOIN Product USING(product_id)
GROUP BY product_id
HAVING MIN(sale_date) >= '2019-01-01' AND MAX(sale_date) <= '2019-03-31';
596. 超过 5 名学生的课 (Classes More Than 5 Students)
题目描述
Courses 表记录了学生选课的情况:
student: 学生。class: 课程名。
请编写一个解决方案,查询至少有 5 名学生 的所有课程。
解题思路
分组统计 + HAVING 子句。
- 将课程表按
class分组。 - 使用
COUNT(*)统计每门课的人数(题目默认 (student, class) 是唯一的,如有重复需加DISTINCT)。 - 过滤出人数大于等于 5 的结果。
SQL 实现 (MySQL)
SELECT class
FROM Courses
GROUP BY class
HAVING COUNT(*) >= 5;
1729. 求关注者的数量 (Find Followers Count)
题目描述
Followers 表保存了社交媒体中的关注关系:
user_id: 用户 ID。follower_id: 关注者的 ID。
请编写一个解决方案,查询每个用户的关注者人数。结果按 user_id 升序排列。
解题思路
简单统计 + 排序。
- 按
user_id分组。 COUNT(follower_id)统计每组人数。
SQL 实现 (MySQL)
SELECT user_id, COUNT(follower_id) AS followers_count
FROM Followers
GROUP BY user_id
ORDER BY user_id;
619. 只出现一次的最大数字 (Biggest Single Number)
题目描述
MyNumbers 表包含一组整数。
单一数字 是指在该表中只出现过一次的数字。请编写一个解决方案,找出最大的单一数字。如果不存在,则返回 null。
解题思路
子查询筛选 + 聚合处理。
- 找出单一数字:使用
GROUP BY num HAVING COUNT(*) = 1获得所有仅出现一次的数字列表。 - 取最大值:在外层查询中对该列表执行
MAX(num)。即便子查询结果为空,MAX()也会返回NULL。
SQL 实现 (MySQL)
SELECT MAX(num) AS num FROM (
SELECT num FROM MyNumbers GROUP BY num HAVING COUNT(*) = 1
) t;
1045. 买下所有产品的客户 (Customers Who Bought All Products)
题目描述
你有两张表:
Customer: 包含customer_id和product_key。Product: 包含product_key(主键)。记录了商店中所有可出售的产品。
请编写一个解决方案,查询买全了 Product 表中 所有产品 的客户 ID。
解题思路
动态维度对比计数。
- 统计产品总数:从
Product表中获知总共有多少种产品:(SELECT COUNT(*) FROM Product)。 - 客户维度统计:对
Customer表按customer_id分组。 - 匹配:筛选出那些购买的不同产品种类数(
COUNT(DISTINCT product_key))等于产品总数的客户。
SQL 实现 (MySQL)
SELECT customer_id
FROM Customer
GROUP BY customer_id
HAVING COUNT(DISTINCT product_key) = (SELECT COUNT(*) FROM Product);
(注:COUNT 必须加 DISTINCT,因为一名顾客可能会多次购买同一种产品)。