查询偏移量 returns 重叠的数据集

Query with offset returns overlapping data sets

最初尝试获得非常简单的分页,使用获取 n 行然后使用偏移量进行后续调用,在 Oracle 中给出了重叠的条目。

我期待以下内容能给我两组独特的结果。如果将第一行的限制设置为 200,将返回结果的 1-100,然后是 101-200。

select  * from "APPR" /*+ index(APPR APPR_IDX01) */ where  ("APPROVER" = 'A') or  ("APPROVER" > 'A') order by "APPROVER"  fetch first 100 rows only ;

select  * from "APPR" /*+ index(APPR APPR_IDX01) */ where  ("APPROVER" = 'A') or  ("APPROVER" > 'A') order by "APPROVER" offset 100 rows fetch next 100 rows only ;

所以如果批准人 A 有 150 个项目,第一个结果应该是:

后续调用(偏移 100)给出

不幸的是,第二组包含第一批值中的一些条目。可能是一个非常愚蠢的错误,但我找不到关于为什么会发生这种情况的解释。

---- 根据评论更新 主键由 Approver 和其他几个字段组成,它们共同构成一个复合且唯一的主键。

代码将通过 ODBC 调用,并将用于 Oracle 和 MySQL 后端。

在 Oracle 中,如果您对包含相同值的列进行“排序依据”(就像您有 - 'A'、'A'、'A' ...)的顺序'A' 值内的记录将是随机的。

请尝试将您的查询更改为... order by "APPROVER", rowid ...

据推测,APPROVER 不是唯一列。由于可能存在重复,order by子句不稳定,offset子句可能会产生重复。

一个简单的解决方案是在 order by 中添加更多列以打破平局。假设 (approver, item) 是一组唯一的列,那就是:

select  * 
from appr
where approver = 'A' or approver > 'A'
order by approver, item
fetch first 100 rows only
-- then: offset 100 rows fetch next 100 rows only

备注:

  • 不需要用双引号将 all-caps 标识符(表名或列名)括起来:这是 Oracle 中的默认设置

  • or 条件周围的括号在这种简单情况下是多余的

  • 如果approver总是一个字符长,那么where子句可以简化为where approver >= 'A'

  • 只有当你真的知道你为什么这样做时才使用索引提示(我不是说你不知道,但我删除了它,以防万一);大多数时候,数据库知道得更多