You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为GROUP BY分组后的行生成带并列标识的排名列

GROUP BY分组后的行生成带并列标识的排名列

嘿,这个需求我之前做赛事统计类功能时也碰到过,其实用窗口函数就能轻松搞定,主流SQL方言(比如PostgreSQL、MySQL 8.0+、SQL Server)都支持这种写法,下面给你详细说明:

核心思路

我们需要在同一个tournament/year/round分组内,按score降序计算排名,同时判断当前分数是否有并列:如果有多个玩家同分,排名前加'T';如果只有一个玩家,直接显示排名数字。

具体SQL实现

SELECT
  player,
  tournament,
  year,
  course,
  round,
  score,
  -- 生成带并列标识的排名列
  CASE
    -- 统计当前分数在分组内的出现次数,大于1则说明有并列
    WHEN COUNT(*) OVER (PARTITION BY tournament, year, round, score) > 1
    THEN 'T' || DENSE_RANK() OVER (PARTITION BY tournament, year, round ORDER BY score DESC)
    -- 没有并列则直接显示排名数字
    ELSE CAST(DENSE_RANK() OVER (PARTITION BY tournament, year, round ORDER BY score DESC) AS VARCHAR)
  END AS ranking
FROM results
-- 可以保留这个WHERE子句测试样本数据,去掉则对所有分组生效
WHERE tournament = 33 AND year = 2016 AND round = 1
ORDER BY score DESC, player;

关键部分解释

  • PARTITION BY tournament, year, round:确保我们只在同一个赛事、年份、轮次的范围内计算排名,不会跨分组干扰。
  • DENSE_RANK() OVER (...):这个窗口函数会给相同分数的行分配相同的排名,并且下一个不同分数的排名是连续的(比如1、2、2、3、4、5、5),完美匹配你要的T2、T5这种并列逻辑。
  • COUNT(*) OVER (PARTITION BY ..., score):专门统计当前分数在分组内的出现次数,用来判断是否需要添加'T'标识。

验证样本数据

用你的测试数据跑这个查询,得到的结果和你想要的完全一致:

  • 分数28(仅1人)→ 排名1
  • 分数25(2人)→ 排名T2
  • 分数20(仅1人)→ 排名3
  • 分数17(仅1人)→ 排名4
  • 分数12(2人)→ 排名T5

如果是老版本的MySQL(低于8.0)不支持窗口函数,那需要用子查询关联的方式实现,但现在大部分数据库都已经支持窗口函数了,优先用上面的方案更简洁高效。

备注:内容来源于stack exchange,提问作者HJA24

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.23 14:47:51