在 SQL 中,要获取每个分组内的前 N 条记录,有哪些常用方法?请说明各自的实现思路和适用场景。
考察说明
考查对 SQL 分组 Top N 查询的多种实现方式及其适用场景的理解。
回答思路
- 【回答框架 1】使用窗口函数 ROW_NUMBER() OVER(PARTITION BY 分组列 ORDER BY 排序列) 为每个分组内的行分配序号,然后在外层查询中过滤序号小于等于 N 的记录。这是最通用和高效的方法,适用于大多数数据库。
- 【回答框架 2】对于不支持窗口函数的旧版 MySQL,可以使用相关子查询或用户变量模拟。相关子查询统计每个分组内大于当前行的数量,当数量小于 N 时即为 Top N。用户变量方式通过排序和变量赋值实现,但性能较慢且逻辑复杂。
- 【回答框架 3】如果只需要每个分组的前 N 个最大值,也可以使用 JOIN 或 EXISTS 等替代方案,但通常不如窗口函数简洁。在选择方法时,应考虑数据库版本、数据量和查询复杂度。
- 【关键点 1】窗口函数 ROW_NUMBER() 是首选,配合 PARTITION BY 和 ORDER BY 使用。
- 【关键点 2】相关子查询适用于不支持窗口函数的场景,但性能较差。
- 【关键点 3】Top N 查询需注意排序字段唯一性,避免并列导致结果不确定。
- 【易错点 1】使用 ROW_NUMBER() 时,如果排序列有重复值,结果不稳定,可根据需求改用 RANK() 或 DENSE_RANK()。
- 【易错点 2】相关子查询在大表上性能极差,应避免在生产环境使用。
- 【易错点 3】用户变量模拟方法依赖执行顺序,逻辑复杂且容易出错,不建议在新代码中使用。