如何通过单条SQL查询获取全量用户对应Top3评分类型的分组记录
合并SQL查询实现需求的方案
当然可以!你完全能把这两步操作合并成单条SQL语句,下面给你几种不同的实现方案,适配不同的数据库方言(比如MySQL、PostgreSQL、SQL Server等),你可以按需选择:
方案1:使用子查询 + IN 子句
这种方式直接在WHERE条件里嵌套子查询,先筛选出总评分排名前三的类型,再过滤原表记录:
SELECT user_id, type, value FROM ratings WHERE type IN ( SELECT type FROM ratings GROUP BY type ORDER BY SUM(value) DESC LIMIT 3 -- 注意:不同数据库取前三的语法有差异,SQL Server用TOP 3,Oracle用FETCH FIRST 3 ROWS ONLY ) ORDER BY user_id, type;
逻辑解释:
- 内层子查询先按
type分组,计算每个类型的总评分SUM(value),按总分降序排序后取前3个类型; - 外层查询直接筛选出原表中
type属于这前三类型的所有记录,最后按user_id和type排序(可选,让结果更规整)。
方案2:使用CTE(公共表表达式)
CTE能把逻辑拆分得更清晰,可读性更强,适合复杂查询:
WITH TopTypes AS ( SELECT type FROM ratings GROUP BY type ORDER BY SUM(value) DESC LIMIT 3 -- 同样注意数据库语法差异 ) SELECT r.user_id, r.type, r.value FROM ratings r JOIN TopTypes tt ON r.type = tt.type ORDER BY r.user_id, r.type;
逻辑解释:
- 先定义
TopTypes这个临时结果集,用来存储总评分前三的类型; - 再将原表
ratings和TopTypes通过type关联,得到符合条件的记录。
方案3:使用窗口函数(适用于支持窗口函数的数据库)
如果你的数据库支持窗口函数(比如MySQL 8+、PostgreSQL、SQL Server),可以用这种更灵活的方式,还能处理同分排名的情况:
SELECT user_id, type, value FROM ( SELECT r.user_id, r.type, r.value, RANK() OVER (ORDER BY SUM(r.value) OVER (PARTITION BY r.type) DESC) AS type_rank FROM ratings r ) ranked_records WHERE type_rank <= 3 ORDER BY user_id, type;
逻辑解释:
- 内层查询中,
SUM(r.value) OVER (PARTITION BY r.type)用来计算每个type的总评分; RANK() OVER (...)根据每个类型的总评分进行排名;- 外层查询筛选出排名<=3的记录,得到最终结果。
注意事项
- 语法差异:不同数据库取前N条的语法不同:
- MySQL/MariaDB:
LIMIT 3 - SQL Server:
SELECT TOP 3 type ... - Oracle:
SELECT type ... ORDER BY SUM(value) DESC FETCH FIRST 3 ROWS ONLY
- MySQL/MariaDB:
- 同分处理:如果有多个类型的总评分相同,
RANK()会给它们相同的排名,可能返回超过3个类型;如果需要严格只取3个,可以改用ROW_NUMBER(),但要确保排序的稳定性(比如再加一个排序字段,比如type)。
内容的提问来源于stack exchange,提问作者BrunoLoops
相关产品推荐
相关产品推荐

