在SQL查询场景中,给结果集添加连续行号是常见需求,可用于分页排序、数据统计等场景。不同数据库的实现方式存在差异,既可以使用内置的窗口函数,也可以通过用户定义变量配合自增逻辑实现。

使用ROW_NUMBER窗口函数添加行号
主流的关系型数据库如MySQL 8.0+、SQL Server、Oracle、PostgreSQL都支持ROW_NUMBER()窗口函数,这是最标准且易用的行号添加方式。该函数会为结果集的每一行生成一个唯一的连续序号,序号顺序由OVER子句中的排序规则决定。
基础语法格式如下:
-- 为查询结果添加行号,按指定字段排序
SELECT
ROW_NUMBER() OVER (ORDER BY 排序字段 [ASC|DESC]) AS row_num,
查询字段1,
查询字段2
FROM 表名
WHERE 过滤条件;
举个例子,假设有一张用户表user_info,包含id、username、age字段,需要按年龄升序给用户添加行号,SQL语句如下:
SELECT
ROW_NUMBER() OVER (ORDER BY age ASC) AS row_num,
id,
username,
age
FROM user_info
WHERE age > 18;
如果需要按分组添加行号,比如按部门分组,每个部门内的员工单独排序编号,可以在OVER子句中添加PARTITION BY分组规则:
-- 按部门分组,每个部门内按入职时间排序添加行号
SELECT
ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY hire_date ASC) AS dept_row_num,
id,
username,
dept_id,
hire_date
FROM employee;
低版本MySQL使用用户定义变量实现自增行号
MySQL 8.0之前的版本不支持窗口函数,此时可以通过用户定义变量配合自增逻辑实现行号添加。用户定义变量以@开头,作用域为当前会话,我们可以在查询过程中定义变量并让其自增。
基础自增行号实现
实现思路是先定义一个初始值为0的行号变量,然后在查询每一行时让变量加1,作为当前行的行号。示例SQL如下:
-- 定义行号变量并初始化,每查询一行自增1
SET @row_num = 0;
SELECT
@row_num := @row_num + 1 AS row_num,
id,
username,
age
FROM user_info
WHERE age > 18
ORDER BY age ASC;
也可以将变量初始化和查询写在一个语句中,避免额外执行SET语句:
SELECT
@row_num := @row_num + 1 AS row_num,
id,
username,
age
FROM user_info, (SELECT @row_num := 0) AS init
WHERE age > 18
ORDER BY age ASC;
这里(SELECT @row_num := 0) AS init的作用是在查询开始时初始化变量@row_num为0,:=是MySQL中的变量赋值运算符。
分组自增行号实现
如果需要实现分组行号,比如按部门分组编号,需要额外定义一个分组标识变量,判断当前行的分组字段是否和上一行一致,不一致则重置行号:
SELECT
-- 如果当前部门id和上一行一致,行号自增,否则重置为1
@row_num := CASE WHEN @prev_dept = dept_id THEN @row_num + 1 ELSE 1 END AS dept_row_num,
@prev_dept := dept_id AS dept_id,
id,
username,
hire_date
FROM employee, (SELECT @row_num := 0, @prev_dept := NULL) AS init
ORDER BY dept_id, hire_date ASC;
在这个逻辑中,@prev_dept用来存储上一行的部门ID,每次查询新行时先判断部门是否变化,再决定行号是自增还是重置,最后更新@prev_dept为当前行的部门ID。
两种方案对比
| 实现方式 | 适用数据库 | 优势 | 劣势 |
|---|---|---|---|
| ROW_NUMBER窗口函数 | MySQL 8.0+、SQL Server、Oracle、PostgreSQL等 | 语法简洁,支持分组排序,性能更稳定,符合SQL标准 | 低版本数据库不支持 |
| 用户定义变量自增 | MySQL所有版本(8.0以下必须用此方式) | 兼容低版本MySQL,实现灵活 | 语法较复杂,依赖会话变量,分组逻辑容易出错,高版本MySQL可能逐步弃用该特性 |
注意事项
- 使用用户定义变量实现行号时,排序逻辑要写在最外层的
ORDER BY中,否则变量自增顺序可能和预期不一致。 - 窗口函数中的排序字段如果有重复值,行号依然是连续的,如果需要相同值行号相同可以使用
RANK()或者DENSE_RANK()函数。 - 用户定义变量的方式在MySQL 8.0+中虽然还能使用,但官方更推荐使用窗口函数,避免后续版本兼容性问题。
实际开发中优先选择窗口函数实现行号添加,只有在低版本数据库不支持的情况下才考虑用户定义变量自增方案。
SQL行号用户定义变量自增技巧ROW_NUMBER函数修改时间:2026-06-16 12:30:35