SQL 用 ROW_NUMBER() 分页为什么会重复数据?
时间:2026-08-22 | 作者:骑光打字机 | 阅读:0根本原因是ORDER BY字段不唯一导致ROW_NUMBER()序号漂移,同一行可能跨页重复出现;必须用子查询/CTE套用、建立匹配索引、避免表达式、防止参数溢出并用唯一列兜底定序。
根本原因不是语法写错了,而是 ORDER BY 字段不唯一,导致数据库每次执行时对相同值的行分配不同物理顺序,ROW_NUMBER() 生成的序号随之漂移——同一行在第1页和第2页都可能出现。
ORDER BY 字段重复时,ROW_NUMBER() 的序号不固定
只要 ORDER BY 中存在重复值(比如多个订单的 created_at = '2026-08-10 14:30:00'),数据库就无法保证这些行之间的相对顺序。这不是 bug,是 SQL 标准允许的未定义行为。
- 第一次查询可能把
id = 105排在同时间组的第1位,分配rn = 101 - 第二次查询它被排到第3位,变成
rn = 103,于是出现在下一页 - 你看到的现象:第1页末尾有
id=105,第2页开头又有id=105
WHERE 条件写错位置,导致全表编号再过滤
不少人会在窗口函数同层直接写 WHERE rn BETWEEN 21 AND 40,可大多数数据库(像SQL Server、PostgreSQL)无法把这个条件下推到窗口计算之前。最终结果是先对全表进行排序编号,然后再过滤。这样一来,不仅性能差、容易导致内存爆满,而且排序过程本身也不稳定。
- 必须用子查询或 CTE 套一层:
SELECT * FROM ( SELECT *, ROW_NUMBER() OVER (ORDER BY created_at DESC, id DESC) AS rn FROM orders ) t WHERE t.rn BETWEEN 21 AND 40
rn别名不能省,漏写会报Invalid column name 'rn'- 别用
rn > 20 AND rn <= 40替代BETWEEN,部分优化器识别不到 TopN 提示
索引没对齐 ORDER BY,强制走 Sort 算子
就算你写了 ORDER BY created_at DESC, id DESC,可要是没建对应的联合索引,数据库就只能全表扫描再加上内存排序(Sort),这样一来,I/O和tempdb的压力会瞬间增大,深分页时延迟会急剧上升,而且排序过程本身就不太稳定。
- 索引必须严格匹配
OVER里的字段顺序和方向:CREATE INDEX IX_orders_time_id ON orders(created_at DESC, id DESC) - 如果常带
WHERE status = 'paid',把status放索引最左列:CREATE INDEX IX_orders_status_time_id ON orders(status, created_at DESC, id DESC) - 避免在排序字段上用表达式,比如
ORDER BY DATE(created_at)或UPPER(name)——索引直接失效
参数计算溢出或越界,让 rn 范围错位
用户传参 @page_index = 0 或 @page_size = 1000 时,(@page_index - 1) * @page_size 可能算出负数或超 int 上限,导致 rn BETWEEN -1 AND 99 这种非法范围。
- 用
DECLARE @offset BIGINT = CAST(@page_index AS BIGINT) - 1避免 int 溢出 - 页码兜底:
DECLARE @page_index INT = ISNULL(NULLIF(@input_page, 0), 1) @page_size建议硬限制 ≤ 100,防止恶意请求触发内存 grant 不足或排序溢出 tempdb
最容易被忽略的一点:你以为加了 ORDER BY 就万事大吉,其实它只是“排序”,不是“定序”——只有加上唯一列兜底,才真正让每一行在逻辑序列中有确定位置。
免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。
相关文章
更多-
- 迅捷路由器怎么调信号最强,设置时要注意什么?
- 时间:2026-08-27
-
- vivo浏览器怎么卸不掉?原因和解决方法在这里
- 时间:2026-08-27
-
- OPPO R11s黑屏了,怎么强制恢复出厂设置?
- 时间:2026-08-27
-
- 飞利浦显示器包装盒有生产日期和保修期吗?怎么看?
- 时间:2026-08-27
-
- 联想新平板开机必须联网吗?怎么做?
- 时间:2026-08-27
-
- 平板横竖屏切换设置与问题解决
- 时间:2026-08-27
-
- 移动电源容量怎么测?要准备哪些工具?
- 时间:2026-08-27
-
- 荣耀90 Pro防水吗?防水级别多少?怎么用才安全
- 时间:2026-08-27
精选合集
更多大家都在玩
大家都在看
更多-
- 糖尿病完全不能吃糖吗
- 时间:2026-09-15
-
- 蚂蚁庄园小课堂2026年9月16日最新题目答案
- 时间:2026-09-15
-
- 小鸡答题今天的答案是什么2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园每日答题答案2026年9月16日
- 时间:2026-09-15
-
- 以下哪种粮食是酿造绍兴黄酒的主要原料 蚂蚁庄园今日答案9月16日
- 时间:2026-09-15
-
- 劝学名句“及时当勉励,岁月不待人”出自哪位诗人 蚂蚁庄园今日答案9.16
- 时间:2026-09-15
-
- 蚂蚁庄园今天答题答案2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园答题今日答案2026年9月16日
- 时间:2026-09-15
