MySQL中实现rank排名查询

本文介绍MySQL中实现排名查询的方法,包括升序、降序排列及不同场景下的排名处理方式。通过具体示例展示如何手动实现类似SQLServer的rank()功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


在MySQL中,不存在类似于SQL Server或Orcal等中的rank()函数来得到排名。

所以我们需要手动地写这个rank功能。

1、基本知识:

◎sql语句中,使用@来定义一个变量。如:@abc

◎sql语句中,使用:=来给变量赋值,如:@abc:=123,则变量abc的值为123

◎sql语句中,if(A,B,C)表示,如果A条件成立,那么执行B,否则执行C,如:

@abc := if(2>1,100,200)的结果是,abc的值为100:

◎case…when…then语句

case…when…then语句有两种情况:

case情况一(CASE 后面不带表达式):

CASE WHEN expression THEN 操作1

       WHEN expression THEN 操作2

        .......

       ELSE 操作n

END

注:自上而下,凡是走了其中一个when或者是走了else了,其他的都不再走了。

case情况二(CASE 后面带表达式,此时WHEN 后面的则是该表达式可能的值):

CASE expression

WHEN expression的值1 THEN 操作1

WHEN expression的值2 THEN 操作2

 .......

ELSE 操作n

END

注:自上而下,凡是走了其中一个when或者是走了else了,其他的都不再走了。

MySQL中,手写rank示例

先创建一个tablle,并放入一些数据,如:
在这里插入图片描述

2、升序排列,排名继续增加

age升序排列(age相同时,排名继续增加),示例:
在这里插入图片描述

注:这里的(SELECT @curRank := 0) q 的作用是:在同一个select语句中给变量curRank赋初始值。效果等同于,两个sql语句,第一个先赋值,第二个再select:
在这里插入图片描述

3、降序排列,排名继续增加

age降序排列(age相同时,排名继续增加),示例:
在这里插入图片描述

4、升序排列,排名不跳级,继续+1,示例一

age升序排列(age相同时,排名相同;但是到下一个age不同时,排名不跳级,继续+1),示例一(case…when…then):
在这里插入图片描述

5、升序排列,排名不跳级,继续+1,示例二

age升序排列(age相同时,排名相同;但是到下一个age不同时,排名不跳级,继续+1),示例二if(a,b,c):
在这里插入图片描述

6、升序排列,排名跳级+n

age升序排列(age相同时,排名相同;但是到下一个age不同时,排名跳级+n),示例:
在这里插入图片描述

注:如果嫌查出来的列太多了,可以再对此结果进行select,如:
在这里插入图片描述


作者:justry_deng
来源:优快云
原文:https://blog.youkuaiyun.com/justry_deng/article/details/80597916

### 在 MySQL 5.6 中实现排名功能的解决方案 由于 MySQL 5.6 不支持窗口函数(如 `RANK()` 和 `DENSE_RANK()`),可以通过使用用户定义变量(User-Defined Variables, UDV)来模拟排名功能。这种方法适用于需要在旧版本数据库中实现类似排名的效果。 #### 用户定义变量的基础概念 用户定义变量是一种临时存储机制,可以在单个会话期间保存值。这些变量以 `@` 开头,并且可以用来跟踪行号或其他累积状态的信息[^4]。 #### 使用用户定义变量实现排名功能 ##### 方法一:简单排名(类似于 `ROW_NUMBER()`) 如果只需要为每一行分配一个唯一的序号,则可以按照如下方式进行操作: ```sql SET @row_number = 0; SELECT t.*, (@row_number := @row_number + 1) AS row_num FROM ( SELECT * FROM your_table ORDER BY some_column DESC -- 根据需求调整排序字段 ) t; ``` 在此示例中,`@row_number` 初始设置为零,随着每次查询迭代增加一,从而实现了逐行为记录赋值的操作[^4]。 ##### 方法二:分组内的排名(类似于 `RANK()` 或 `DENSE_RANK()`) 当希望在同一组内部进行排名时,还需要额外考虑如何重置计数器以及处理平局情况下的排名逻辑。这里提供了一个基本框架供参考: ```sql SET @prev_value = NULL; SET @rank = 0; SET @dense_rank = 0; SELECT id, score, CASE WHEN @prev_value = score THEN @rank ELSE @rank := @rank + 1 END AS rank_val, CASE WHEN @prev_value = score THEN @dense_rank ELSE @dense_rank := @dense_rank + 1 END AS dense_rank_val, @prev_value := score FROM ( SELECT id, score FROM your_table ORDER BY score DESC -- 根据需求调整排序字段 ) t; ``` 在这个例子里面,我们维护两个不同的等级序列——一个是普通的排名 (`rank_val`) ,它会在遇到相同分数的时候跳过某些数值;另一个则是紧密型排名(`dense_rank_val`),即便有重复项也只会连续增长[^1]。 注意:上述脚本中的 `CASE...WHEN` 结构是用来判断当前行与前一行是否存在差异,进而决定是否更新对应的排名指标。同时通过将当前比较过的列重新赋值给 `@prev_value` 来准备下一轮循环的数据对比工作。 #### 处理复杂场景下的注意事项 - **初始化变量**:确保每次执行之前都先正确设置了初始条件,否则可能导致意外的结果。 - **事务隔离级别**:考虑到并发环境的影响,在高负载或者分布式环境中应用此类技巧时要特别小心,必要时候应提升事务的一致性和可串行化程度。 - **性能考量**:虽然UDV提供了灵活性,但对于非常大的数据集来说可能会带来显著开销,因此建议测试不同规模数据的表现后再做最终决策。 综上所述,尽管缺乏原生的支持工具,但借助巧妙运用MySQL内置特性仍然能够在较老版本里达成预期目标。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值