PostgreSQL按ID分组并返回最高RANK值的正确SQL写法
解决按ID分组获取最高RANK值的SQL问题
首先先明确你的表数据(这里假设表名为your_table,你可以替换成实际表名):
+------+--------+ | RANK | ID | +------+--------+ | 1 | 234 | | 2 | 234 | | 3 | 234 | | 1 | 421 | | 2 | 421 | +------+--------+
你的需求是按ID分组,返回每个ID对应的最高RANK值,但你写的SQL存在几个语法和逻辑问题:
- SQL语句顺序错误:
WHERE子句必须放在GROUP BY之前,正确执行顺序是FROM→WHERE→GROUP BY→SELECT; - 使用
GROUP BY时,SELECT子句里的列要么是分组列,要么是聚合函数,不能直接用SELECT *; max(RANK)是聚合函数,不能直接放在WHERE中(WHERE过滤的是原始行,聚合后的条件才用HAVING,但这里你不需要过滤分组,而是要计算每组的最大值)。
正确的实现方法
方法1:基础聚合查询(仅返回ID和最高RANK)
这是最直接的方式,通过GROUP BY分组后,用MAX()聚合函数获取每组的最高RANK:
SELECT ID, MAX(RANK) AS highest_rank FROM your_table GROUP BY ID;
执行后会得到预期结果:
+--------+--------------+ | ID | highest_rank | +--------+--------------+ | 234 | 3 | | 421 | 2 | +--------+--------------+
方法2:窗口函数(返回最高RANK对应的完整行)
如果需要获取每个ID最高RANK对应的完整行(比如表中还有其他列需要展示),可以用窗口函数ROW_NUMBER():
SELECT t.* FROM ( SELECT *, -- 按ID分区,每个分区内按RANK降序排序,给每行编号 ROW_NUMBER() OVER (PARTITION BY ID ORDER BY RANK DESC) AS row_num FROM your_table ) t -- 取每个分区的第一行(即最高RANK的行) WHERE t.row_num = 1;
如果某个ID存在多个相同最高RANK的行,ROW_NUMBER()只会返回其中一行。若想保留所有最高RANK的行,可把ROW_NUMBER()换成RANK()或DENSE_RANK():
SELECT t.* FROM ( SELECT *, RANK() OVER (PARTITION BY ID ORDER BY RANK DESC) AS row_rank FROM your_table ) t WHERE t.row_rank = 1;
内容的提问来源于stack exchange,提问作者Jack_Carver
相关产品推荐
相关产品推荐

