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

MySQL如何实现OVER(PARTITION BY)分区排名?SQL Server可行遇阻求助

搞定MySQL分区内的自定义排名需求

嘿,从你给的示例和需求来看,你要的是按Name分组,每个组里把Price从高到低排,然后给每行分配一个从1开始往上数的排名——最大的Price对应组里最大的排名数,最小的对应1,而且相同Price的行也会按顺序拿到连续的排名(不会并列)。

下面分两种MySQL版本给你具体的实现方案:

一、MySQL 8.0+(推荐,支持窗口函数)

MySQL 8.0及以上已经支持OVER(PARTITION BY)这类窗口函数,和SQL Server的语法几乎一致,实现起来很简单。你可以用两种思路来写:

思路1:反转降序行号

先给每个分组内按Price降序分配行号,再用分组总行数减去行号得到目标排名:

SELECT 
    Name,
    Price,
    COUNT(*) OVER(PARTITION BY Name) - ROW_NUMBER() OVER(PARTITION BY Name ORDER BY Price DESC) + 1 AS Rank
FROM MyTable
ORDER BY Name, Price DESC;

思路2:直接升序行号(更简洁)

既然最小的Price对应排名1,那直接按Price升序给每个分组分配行号,最后再按Name和Price降序输出即可:

SELECT 
    Name,
    Price,
    ROW_NUMBER() OVER(PARTITION BY Name ORDER BY Price ASC) AS Rank
FROM MyTable
ORDER BY Name, Price DESC;

两种写法都能得到你想要的结果,思路2更直观易懂,推荐使用。

二、MySQL 5.7及以下(不支持窗口函数)

如果你的MySQL版本还停留在5.7或更早,就得用用户变量来模拟分区排名的逻辑:

SELECT 
    Name,
    Price,
    @rank := CASE 
        WHEN @current_name = Name THEN @rank + 1 
        ELSE 1 
    END AS Rank,
    @current_name := Name
FROM (
    -- 先按分组和Price升序排序,确保最小Price排在组内最前面
    SELECT Name, Price 
    FROM MyTable 
    ORDER BY Name, Price ASC
) AS t,
-- 初始化变量:记录当前分组名称和当前排名
(SELECT @current_name := '', @rank := 0) AS vars
-- 最后按分组和Price降序输出,匹配期望格式
ORDER BY Name, Price DESC;

逻辑解释:

  1. 子查询t先把数据按Name分组、Price升序排序,这样每个组里最小的Price会排在最前面
  2. 用@current_name跟踪当前处理的分组名称,@rank记录当前组的排名序号
  3. 当处理的行和上一行属于同一个分组时,排名加1;如果切换到新分组,排名重置为1
  4. 外层查询再按Name和Price降序排序,输出你期望的格式

验证结果

不管用哪种方案,执行后都会得到你想要的结果:

Name | Price | Rank
abs | 200 | 4
abs | 100 | 3
abs | 60 | 2
abs | 10 | 1
qwe | 50 | 4
qwe | 25 | 3
qwe | 10 | 2
qwe | 10 | 1
trx | 20 | 2
trx | 19 | 1

内容的提问来源于stack exchange,提问作者s-dept

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:44:10