题目描述
该题目要求我们找出每所学校 GPA 最低的同学。我们需要从user_profile
表中获取相关信息,该表包含字段id
、device_id
、gender
、age
、university
、gpa
、active_days_within_30
、question_cnt
、answer_cnt
。我们需要输出每所学校的最低 GPA,以及对应的同学设备 ID 和学校名称,并且查询结果需按照university
升序排序。
题目分析
解决这道题的核心在于如何精准地定位每所学校中 GPA 最低的同学记录(注意,不是只需要找到每所学校的用户中最低GPA是多少)。这就要求我们必须正确地对数据进行分组,将同一学校的数据归为一组,然后在每组中筛选出 GPA 最小的记录。其中,实现分组和最小值筛选的具体操作是解题的关键与难点。
两种解法思路详解
解法一:窗口函数法
利用窗口函数ROW_NUMBER()
来实现。具体做法是以university
字段作为分区依据,将数据按学校进行分区。在每个分区内,依据gpa
字段进行升序排序,然后为每个分区内的记录生成一个序号。如此一来,每所学校内 GPA 最低的同学所对应的序号即为 1,最后只需筛选出序号为 1 的记录,就能得到我们想要的结果。
解法二:聚合函数法
首先通过子查询,使用GROUP BY university
对数据按学校进行分组,再利用MIN(gpa)
聚合函数找出每所学校的最低 GPA。接着在主查询中,从user_profile
表中筛选出gpa
字段值等于子查询中得到的每所学校最低 GPA 的记录,从而获取所需信息。
两种解法思路总结
两种解法本质上都是想方设法定位每所学校中GPA最低的记录,个人觉得相较而言聚合函数的方法能够让代码更加简洁,也相对好想一些,适合新手小白;窗口函数的方法则更高端一些,适合想要提升自己SQL能力的同学训练自己的代码思路。
两种解法代码详解
解法一:窗口函数法
SELECT device_id, university, gpa
FROM (
SELECT device_id, university, gpa,
ROW_NUMBER() OVER(PARTITION BY university ORDER BY gpa ASC) AS rn
FROM user_profile
) AS d1
WHERE rn = 1
ORDER BY university;
关键点
PARTITION BY university
:明确按照university
字段进行分区,确保同一学校的数据在同一分区内;ORDER BY gpa ASC
:在每个分区内,依据gpa
字段进行升序排序,这样 GPA 最低的记录会排在分区的首位;ROW_NUMBER()
:生成序号,后续通过判断序号rn
是否等于 1,来筛选出每个学校 GPA 最低的记录。
解法二:聚合函数法
SELECT device_id, university, gpa
FROM user_profile
WHERE gpa in (
SELECT MIN(gpa)
FROM user_profile
GROUP BY university
)
ORDER BY university;
关键点
- 子查询
SELECT MIN(gpa) FROM user_profile GROUP BY university
:通过分组和聚合函数,找出每个学校的最低 GPA。 - 主查询中的
WHERE gpa in (...)
:利用IN
关键字,筛选出user_profile
表中gpa
字段值等于子查询结果的记录,从而得到每个学校 GPA 最低的同学信息。 ORDER BY university
:对最终结果按照university
字段进行升序排序,满足题目要求。