我多年来一直使用相同的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,那么分页“会中断”。
也就是说,查询将返回页面后相同的精确行数据页面。当我想到它时,为什么不呢。它可能只是选择最快的行或任何通过过滤器的行。
所以例如,这些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;
大多数时候我只是觉得这很整洁。我在其他帖子中没有看到太多副作用。
而且,我想知道我能做些什么......以及其他策略是否会增加处理时间。
来自戈登的解决方案,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;
stackoverflow的另一个胜利,谢谢gentelmen,快乐编码每个人
答案 0 :(得分:5)
SQL表表示无序集。因此,SQL排序不是稳定。也就是说,具有相同键值的行可以按任何顺序排列 - 并且在多次运行中,顺序可以更改。行没有“基础”订单。
解决方案是在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;
这是否会影响性能取决于索引是否可用于排序。如果没有使用索引,则效果应该非常小。但是,如果添加额外的密钥可以防止使用索引,那么影响就会大得多。