MySQL如何实现类似SQL Server的Partition分区排名?求助实现指定逻辑
嘿,作为刚从SQL Server转MySQL的新手,遇到这种排名需求差异太正常了!我来帮你搞定这个分组排名的问题。
首先先明确你的需求:按Name分组,组内按Price从高到低展示,同时Rank值从组内最低Price对应的1开始,递增到最高Price对应的组内行数——简单说就是组内升序Price的排名,倒过来和降序Price一起展示。
方法一:MySQL 8.0+ 用窗口函数(推荐)
MySQL 8.0及以上版本支持窗口函数,这是实现这类需求最简洁高效的方式:
SELECT Name, Price, ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Price ASC) AS `Rank` FROM MyTable ORDER BY Name, Price DESC;
解释:
PARTITION BY Name:将数据按Name分组,每个组单独计算排名ORDER BY Price ASC:在每个组内,按Price升序给每行分配序号,这样最低Price的行得到Rank=1,最高Price的行得到组内总行数的序号- 外层的
ORDER BY Name, Price DESC:让最终结果按Name分组,组内Price从高到低排列,正好对应你要的Rank顺序
方法二:MySQL 5.x 版本用用户变量
如果你的MySQL版本低于8.0,没有窗口函数,可以用用户变量来实现:
-- 初始化变量 SET @prev_name = ''; SET @rank = 1; SELECT Name, Price, `Rank` FROM ( SELECT Name, Price, -- 同一组内rank递增,换组则重置为1 IF(@prev_name = Name, @rank := @rank + 1, @rank := 1) AS `Rank`, @prev_name := Name FROM MyTable -- 先按组内Price升序排序,为rank赋值做准备 ORDER BY Name, Price ASC ) AS temp_result -- 最终按组内Price降序输出 ORDER BY Name, Price DESC;
解释:
- 先初始化两个变量:
@prev_name记录上一行的Name,@rank记录当前排名 - 子查询里先按
Name和Price升序排序,然后通过IF判断:如果当前行Name和上一行相同,rank加1;否则重置为1 - 外层查询再按
Name和Price降序排列,得到你想要的结果
这两种方法都能得到你预期的结果,比如qwe组的两个10会分别得到Rank=2和Rank=1,完全符合你的示例需求。
内容的提问来源于stack exchange,提问作者s-dept
相关产品推荐
相关产品推荐

