SQL中生成序列号主要靠窗口函数ROW_NUMBER(),它按ORDER BY指定顺序为每行分配严格连续的唯一编号;支持PARTITION BY分组内独立编号;与RANK()、DENSE_RANK()不同,ROW_NUMBER()不处理重复值,始终连续递增。

SQL 中生成序列号主要靠窗口函数 ROW_NUMBER(),它能按指定顺序为每一行分配唯一递增编号,不依赖表中现有字段,也不修改数据。
用 ROW_NUMBER() 生成基础序列号
最常用方式是配合 OVER() 子句。ORDER BY 是必需的,否则语法报错;通常按某列排序来定义“顺序”:
SELECT ROW_NUMBER() OVER (ORDER BY id) AS seq_no, name, score FROM students;
结果中 seq_no 从 1 开始,按 id 升序连续编号。注意:即使 id 本身不连续(如缺 3、5),ROW_NUMBER() 仍输出 1,2,3,4…
按分组生成独立序列号
加 PARTITION BY 可在每个组内重新计数。比如给每个班级的学生单独排号:
SELECT class, ROW_NUMBER() OVER (PARTITION BY class ORDER BY score DESC) AS rank_in_class, name, score FROM students;
每个班级内,分数最高的学生 rank_in_class = 1,依次类推。不同班级的序号互不影响。
与其他编号函数的区别
容易混淆的是 RANK() 和 DENSE_RANK():
- ROW_NUMBER():严格连续,相同值也给不同序号(如 1,2,3)
- RANK():跳过重复名次(如分数并列第1 → 下一个是第3)
- DENSE_RANK():不跳过(如并列第1 → 下一个是第2)
要纯“序号”而非“排名”,必须用 ROW_NUMBER()。
不支持窗口函数的老版本怎么办?
MySQL 5.7 或更早、SQL Server 2005 以前等不支持 OVER 的环境,可用变量模拟:
SET @row := 0; SELECT @row := @row + 1 AS seq_no, name, score FROM students ORDER BY id;
注意:必须显式 ORDER BY 保证顺序,且变量赋值和查询需在同一语句中(或用子查询包装)。这种方式可读性差、并发不安全,仅作兼容方案。










