如何在MySQL 5.7中不使用RANK()和PARTITION BY实现排名功能
MySQL 5.7 适配分组排名功能解决方案
MySQL 5.7 版本不支持RANK()、PARTITION BY这类窗口函数语法,我们可以通过用户自定义变量的方式模拟对应逻辑,实现和参考SQL完全一致的效果,适配语句如下:
SELECT category, brands, revenue, `rank` FROM ( SELECT t.*, -- 统计当前分类下的行序号,用于实现跳跃排名 @row_num := IF(@prev_category = category, @row_num + 1, 1) AS temp_row_num, -- 同分类同营收排名不变,同分类不同营收取当前行序号作为新排名,跨分类重置排名为1 @rank := IF(@prev_category = category, IF(@prev_revenue = revenue, @rank, @row_num), 1) AS `rank`, -- 缓存当前行的分类、营收值,用于下一行的对比判断 @prev_category := category, @prev_revenue := revenue FROM task.ranking t, -- 初始化所有自定义变量 (SELECT @prev_category := NULL, @prev_revenue := NULL, @rank := 0, @row_num := 0) init -- 必须先按分组字段排序,再按排名字段排序,和原窗口函数逻辑一致 ORDER BY category, revenue ) res ORDER BY category;
注意事项
- 内层查询的
ORDER BY字段顺序必须严格和原窗口函数的PARTITION BY、ORDER BY字段顺序一致,变量是按排序后的行顺序逐行计算的,顺序错误会导致排名结果不符合预期 - 变量判断逻辑必须写在变量赋值逻辑之前,避免先把当前行的值覆盖了缓存的上一行值,导致判断出错
- 如果需要连续排名效果(对应
DENSE_RANK()窗口函数),可将@rank的赋值逻辑修改为:@rank := IF(@prev_category = category, IF(@prev_revenue = revenue, @rank, @rank + 1), 1) AS `rank`
内容的提问来源于stack exchange,提问作者shalu
相关产品推荐
相关产品推荐

