跳到主要内容

排序和分组

排序 (ORDER BY) 和分组 (GROUP BY) 常用于按照特定维度对数据块进行过滤和去重统计。

2356. 每位教师所教授的科目种类的数量 (Number of Unique Subjects Taught by Each Teacher)

题目描述

Teacher 表保存了教师教授科目和在哪个系教授的信息:

  • teacher_id: 教师 ID。
  • subject_id: 科目 ID。
  • dept_id: 系 ID。

请编写一个解决方案,计算每位老师在大学里教授的 不同 科目的数量。

解题思路

去重统计 + 分组

  1. GROUP BY teacher_id 将教师进行分组。
  2. 对每组中的 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 天内,每日活跃用户的数量(至少进行过一次活动的用户即为活跃用户)。

解题思路

日期范围过滤 + 分组计数

  1. 时间窗口:2019-07-27 的前 30 天,即起始日期为 2019-07-27 - 29,对应区间为 [2019-06-28, 2019-07-27]
  2. 聚合:关键在于 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-012019-03-31)销售的产品。

解题思路

聚合条件筛选 (HAVING)

  1. Product 表与 Sales 表关联。
  2. GROUP BY product_id
  3. 条件:该产品销售记录中的 最小值日期最大值日期 必须全部处于第一季度范围内。如果最小日期小于一月或最大日期大于三月,则说明在其他季度也有销售,不符合“仅”的要求。

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 子句

  1. 将课程表按 class 分组。
  2. 使用 COUNT(*) 统计每门课的人数(题目默认 (student, class) 是唯一的,如有重复需加 DISTINCT)。
  3. 过滤出人数大于等于 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 升序排列。

解题思路

简单统计 + 排序

  1. user_id 分组。
  2. 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

解题思路

子查询筛选 + 聚合处理

  1. 找出单一数字:使用 GROUP BY num HAVING COUNT(*) = 1 获得所有仅出现一次的数字列表。
  2. 取最大值:在外层查询中对该列表执行 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_idproduct_key
  • Product: 包含 product_key (主键)。记录了商店中所有可出售的产品。

请编写一个解决方案,查询买全了 Product 表中 所有产品 的客户 ID。

解题思路

动态维度对比计数

  1. 统计产品总数:从 Product 表中获知总共有多少种产品:(SELECT COUNT(*) FROM Product)
  2. 客户维度统计:对 Customer 表按 customer_id 分组。
  3. 匹配:筛选出那些购买的不同产品种类数(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,因为一名顾客可能会多次购买同一种产品)