题目描述

该题目要求我们找出每所学校 GPA 最低的同学。我们需要从user_profile表中获取相关信息,该表包含字段iddevice_idgenderageuniversitygpaactive_days_within_30question_cntanswer_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字段进行升序排序,满足题目要求。