sql 当 'order by' 不确定时分页

sql pagination when 'order by' non-deterministic

多年来我一直在使用相同的 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>>`

如果 some_column 是连续的,效果会很好。

但我公开了这一点并允许用户对任何列进行排序,如果他们碰巧选择了 some_column,那将充满相同的值 - 分页 'breaks'。

也就是说,查询将return相同的确切行数据页接一页。当我考虑它时,为什么不呢。它可能只是选择最快的行或通过过滤器的任何内容。

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

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;

大多数情况下,我只是觉得这很好,我在其他帖子中并没有看到太多关于这种副作用的信息。

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

解决方案 来自 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;

Whosebug 的又一次胜利,感谢先生们,祝大家编码愉快

SQL 表表示无序集。因此,SQL 排序不稳定 。也就是说,具有相同键值的行可以按任何顺序排列——而且在多次运行时顺序可以改变。行没有 "underlying" 顺序。

解决方法是在order by的末尾添加一个唯一的id。这将始终是最后一个键:

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

这是否影响性能取决于是否可以使用索引进行排序。如果不使用索引,那么影响应该很小。但是,如果添加额外的键会阻止使用索引,那么影响会更大。