在mysql的查询场景中,经常需要为返回的结果集添加连续的序号,用于标识每条记录的位置,或者满足分页、排名等业务需求。不同的mysql版本支持的功能不同,添加序号的实现方式也有区别,下面介绍几种常用的实现方案。

使用窗口函数添加序号
mysql 8.0及以上版本支持窗口函数,其中ROW_NUMBER()是最常用的生成序号的函数,它会为结果集的每一行生成一个唯一的连续序号,序号从1开始递增。
基本语法如下:
-- 按指定排序规则生成序号
SELECT
ROW_NUMBER() OVER (ORDER BY 排序字段 [ASC|DESC]) AS 序号,
其他查询字段
FROM 表名
[WHERE 筛选条件];
举个例子,假设有一张student表,存储学生的id、姓名和成绩,现在需要按成绩从高到低查询学生信息并添加序号:
SELECT
ROW_NUMBER() OVER (ORDER BY score DESC) AS rank_num,
id,
name,
score
FROM student;
如果需要按某个分组分别生成序号,比如按班级分组,每个班级内按成绩排序生成序号,可以在OVER子句中添加PARTITION BY:
SELECT
ROW_NUMBER() OVER (PARTITION BY class_id ORDER BY score DESC) AS class_rank,
id,
name,
class_id,
score
FROM student;
使用用户变量添加序号
如果使用的mysql版本低于8.0,不支持窗口函数,可以通过用户变量的方式实现序号添加。用户变量可以存储一个值,在查询过程中可以对其进行修改和引用。
实现思路是定义一个用户变量初始值为0,每查询一行记录就让变量加1,将变量的值作为序号返回。
基础实现示例如下:
-- 定义变量并初始化
SET @row_num = 0;
-- 查询时递增变量
SELECT
@row_num := @row_num + 1 AS seq,
其他查询字段
FROM 表名
ORDER BY 排序字段;
也可以将变量初始化和查询写在同一个语句中,避免单独执行初始化操作:
SELECT
@row_num := @row_num + 1 AS seq,
id,
name,
score
FROM student, (SELECT @row_num := 0) AS init
ORDER BY score DESC;
如果需要按分组生成序号,用户变量的实现会稍微复杂一些,需要额外定义一个分组变量来记录上一个分组的字段值,判断是否需要重置序号:
SELECT
-- 如果当前分组字段和上一个相同,序号加1,否则重置为1
@row_num := IF(@prev_class = class_id, @row_num + 1, 1) AS class_seq,
@prev_class := class_id AS class_id,
id,
name,
score
FROM student, (SELECT @row_num := 0, @prev_class := NULL) AS init
ORDER BY class_id, score DESC;
通过自连接的方式添加序号
除了上述两种方式,还可以通过自连接实现序号添加,这种方式不需要窗口函数也不需要用户变量,但是性能相对较差,适合数据量较小的场景。
实现原理是对于结果集中的每一行,统计比它排序字段值小(或排序优先级高)的记录数量,数量加1就是当前行的序号。
示例代码如下:
SELECT
(SELECT COUNT(*) FROM student s2 WHERE s2.score > s1.score) + 1 AS seq,
s1.id,
s1.name,
s1.score
FROM student s1
ORDER BY s1.score DESC;
这种方式如果排序字段存在相同值,生成的序号会不连续,比如两个学生成绩相同,它们的序号会是相同的,后续序号会跳过对应的数量。
不同方式的对比
下面是几种方式的对比情况:
| 实现方式 | 适用版本 | 优点 | 缺点 |
|---|---|---|---|
| ROW_NUMBER窗口函数 | mysql 8.0及以上 | 语法简洁,支持分组排序,性能好 | 低版本mysql不支持 |
| 用户变量 | 所有mysql版本 | 兼容性好,实现灵活 | 语法相对复杂,分组场景需要额外处理 |
| 自连接 | 所有mysql版本 | 不需要特殊功能支持 | 性能差,数据量大时效率低,相同值处理不友好 |
注意事项
- 使用窗口函数时,
OVER子句中的排序规则会直接影响序号的生成顺序,需要和查询的整体排序规则保持一致,避免序号和记录顺序不匹配。 - 用户变量的方式在mysql 8.0之后的版本中,不保证执行顺序,可能会出现序号生成异常的情况,因此高版本优先使用窗口函数。
- 如果查询包含
DISTINCT、GROUP BY等操作,序号的生成需要放在这些操作之后,避免序号计算错误。 - 自连接方式在排序字段有重复值时,生成的序号不会连续,如果需要连续序号不建议使用这种方式。
mysql查询序号ROW_NUMBER用户变量排序修改时间:2026-06-25 13:18:36