MySQL 5.7不支持DENSE_RANK()函数,求替代实现方案
在MySQL 5.7中实现DENSE_RANK()效果的替代方案
由于MySQL 5.7不支持窗口函数DENSE_RANK(),我们可以通过用户变量模拟相同的排名逻辑——相同分数获得相同排名,排名连续不跳跃。
实现步骤
- 先计算出排序用的核心分数值(即原语句中
ORDER BY后的复杂表达式),命名为score。 - 按
score倒序排序结果集。 - 使用用户变量跟踪上一行的分数和当前排名,动态计算每一行的dense rank。
完整替代代码
SELECT t.*, @curr_rank := CASE WHEN @prev_score = t.score THEN @curr_rank ELSE @curr_rank + 1 END AS dens_rank, @prev_score := t.score FROM ( -- 替换为你原始查询的主逻辑,保留score计算 SELECT -- 你的其他查询字段 ( IFNULL( (SUM(CASE WHEN DATEDIFF(lt.dispatch_date, t.received_at) <=2 OR DATEDIFF(t.received_at, t.created_at) <=2 THEN 1 ELSE 0 END) /( SUM(CASE WHEN DATEDIFF(lt.dispatch_date, t.received_at) <=2 OR DATEDIFF(t.received_at, t.created_at) <=2 THEN 1 ELSE 0 END) + SUM(CASE WHEN DATEDIFF(lt.dispatch_date, t.received_at) >2 OR DATEDIFF(t.received_at, t.created_at) >2 THEN 1 ELSE 0 END) )) *100, 0 ) + IFNULL( (IFNULL(SUM(DATEDIFF(d.created_at, t.received_at) <=2), 0) /( IFNULL(SUM(DATEDIFF(d.created_at, t.received_at) <=2), 0) + IFNULL(SUM(DATEDIFF(d.created_at, t.received_at) >2), 0) )) *100, 0 ) ) /2 AS score FROM -- 你的表关联逻辑(比如t、lt、d等表的JOIN) your_table t JOIN other_table lt ON t.id = lt.t_id JOIN another_table d ON t.id = d.t_id GROUP BY -- 你的分组字段(比如t.id等) t.id ORDER BY score DESC ) t, (SELECT @curr_rank := 0, @prev_score := NULL) vars
代码说明
- 内层子查询:计算每个分组的
score值,并按score倒序排列,这是排名的基础。 - 用户变量初始化:
(SELECT @curr_rank := 0, @prev_score := NULL) vars初始化排名计数器和上一行分数变量。 - 排名计算:通过
CASE语句判断当前行的score是否与上一行相同:- 相同则保持当前排名不变;
- 不同则排名加1,同时更新上一行分数变量。
这种写法完全适配MySQL 5.7,能实现和DENSE_RANK() OVER (ORDER BY score DESC)一致的排名效果。
内容的提问来源于stack exchange,提问作者mohammad shafi
相关产品推荐
相关产品推荐

