当'order by'非确定性时,sql分页

Ste*_*lds 2 sql oracle paging pagination sql-order-by

多年来我一直在使用相同的sql分页代码.我现在才注意到这种奇怪的现象......我认为它非常有趣,我们应该讨论它.所以这是标准的分页样板:

  SELECT a.*
  FROM (SELECT b.*,
               rownum b_rownum
          FROM (SELECT c.*
                  FROM some_table c
                 ORDER BY some_column) b
         WHERE rownum <= <<upper limit>>) a
 WHERE b_rownum >= <<lower limit>>`
Run Code Online (Sandbox Code Playgroud)

如果some_column是连续的,那么它的效果很棒.

但我暴露了这一点,并允许用户对任何列进行排序,如果他们碰巧选择了一些充满相同值的some_column,那么分页"会中断".

也就是说,查询将返回页面后相同的精确行数据页面.当我想到它时,为什么不呢.它可能只是选择最快的行或通过过滤器的任何东西.

例如,这些sql返回完全相同的数据

select *
from (select a.*, ROWNUM rnum
      from ( select * from xsd order by PREFIX asc ) a
      where ROWNUM <= 30
     )
where rnum  >= 20;


select *
from (select a.*, ROWNUM rnum
      from ( select * from xsd order by PREFIX asc ) a
      where ROWNUM <= 40
     )
where rnum  >= 30;
Run Code Online (Sandbox Code Playgroud)

大多数情况下,我只是认为这很整洁,而且我在其他帖子中没有看到太多副作用.

而且,我想知道我能做些什么......以及其他策略是否会增加处理时间.

来自Gordon,Alex的解决方案

只需将rowid添加为默认的最终订单.这些SQL现在不同了.我没有注意到响应时间的任何变化

select *
from (select a.*, ROWNUM rnum
      from ( select * from xsd order by PREFIX asc, rowid ) a
      where ROWNUM <= 30
     )
where rnum  >= 20;


select *
from (select a.*, ROWNUM rnum
      from ( select * from xsd order by PREFIX asc, rowid ) a
      where ROWNUM <= 40
     )
where rnum  >= 30;
Run Code Online (Sandbox Code Playgroud)

stackoverflow的另一个胜利,谢谢gentelmen,快乐编码每个人

Gor*_*off 5

SQL表表示无序集.因此,SQL排序不稳定.也就是说,具有相同键值的行可以按任何顺序排列 - 并且在多次运行中,顺序可以更改.行没有"基础"顺序.

解决方案是在结尾添加一个唯一的id order by.这永远是最后一把钥匙:

select *
from (select a.*, ROWNUM as rnum
      from ( select * from xsd order by PREFIX asc, id ) a
      where ROWNUM <= 40
     )
where rnum  >= 30;
Run Code Online (Sandbox Code Playgroud)

这是否会影响性能取决于索引是否可用于排序.如果没有使用索引,则效果应该非常小.但是,如果添加额外的密钥可以防止使用索引,那么影响就会大得多.