问题描述
亲爱的团队,
我们有一个有点复杂的SQL,包括一个外部连接,我们在多次获取期间看到保留行顺序的问题。
SQL的结构如下。
SELECT
FROM
OUTER JOIN
ORDER BY ASC
ORDER BY在非键栏上。我们有duplicate values对于这个非键列。
当我们运行语句以获取从rownum 10到25的行时,重复值的集合按预期排序。
偏移0行仅获取前25行
当你运行语句时,你会得到前16行; 按预期工作。
偏移0行仅获取前16行
但是,当您运行相同的语句以获取接下来的50行时,some of the rows already listed in previous query is resulted which is not the expected outcome。
偏移量17行仅获取前50行
Note that this happens only when the sorting column contains few duplicate values & the previous fetch stops at the middle of the duplicate values。
然而,当我们remove the outer join, this works as expected。 i。e。 50 rows from rownum 17 does not include items populated in previous step 1-16。 Row order is preserved in that case。
当涉及到外部连接存在的情况时,这可能是一个错误吗?
Expert advice is welcome here。
谢谢 & 致以最诚挚的问候,
纳文思
我们有一个有点复杂的SQL,包括一个外部连接,我们在多次获取期间看到保留行顺序的问题。
SQL的结构如下。
SELECT
FROM
OUTER JOIN
ORDER BY
ORDER BY在非键栏上。我们有duplicate values对于这个非键列。
当我们运行语句以获取从rownum 10到25的行时,重复值的集合按预期排序。
偏移0行仅获取前25行
当你运行语句时,你会得到前16行; 按预期工作。
偏移0行仅获取前16行
但是,当您运行相同的语句以获取接下来的50行时,some of the rows already listed in previous query is resulted which is not the expected outcome。
偏移量17行仅获取前50行
Note that this happens only when the sorting column contains few duplicate values & the previous fetch stops at the middle of the duplicate values。
然而,当我们remove the outer join, this works as expected。 i。e。 50 rows from rownum 17 does not include items populated in previous step 1-16。 Row order is preserved in that case。
当涉及到外部连接存在的情况时,这可能是一个错误吗?
Expert advice is welcome here。
谢谢 & 致以最诚挚的问候,
纳文思
专家解答
在封面下,我们将 “提取/偏移” 子句重新映射到简单的排序函数,例如
所以查询相当于
每当你有重复,然后分配 “row_number” 到这些重复是任意的,例如,如果我有enames:
棕色
琼斯
琼斯
琼斯
史密斯
然后根据执行计划,我可以得到 * 任何 * 以下排序:
棕色 1
琼斯 2
琼斯 3
琼斯 4
史密斯 5
或者
棕色 1
琼斯 4
琼斯 3
琼斯 2
史密斯 5
或者
棕色 1
琼斯 2
琼斯 4
琼斯 3
史密斯 5
etc etc...This is the same with *any* 或者der by clause by the way. The only way to ensure deterministic results is to 或者der by something that does not have duplicates. The easiest way is to use something unique as a tie-breaker, eg
SQL> select * from scott.emp 2 或者der by ename 3 offset 0 rows fetch first 10 rows only; EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ---------- ---------- --------- ---------- --------- ---------- ---------- ---------- 7876 ADAMS CLERK 7788 12-JAN-83 1100 20 7499 ALLEN SALESMAN 7698 20-FEB-81 1600 300 30 7698 BLAKE MANAGER 7839 01-MAY-81 2850 30 7782 CLARK MANAGER 7839 09-JUN-81 2450 10 7902 FORD ANALYST 7566 03-DEC-81 3000 20 7900 JAMES CLERK 7698 03-DEC-81 950 30 7566 琼斯 MANAGER 7839 02-APR-81 2975 20 7839 KING PRESIDENT 17-NOV-81 5000 10 7654 MARTIN SALESMAN 7698 28-SEP-81 1250 1400 30 7934 MILLER CLERK 7782 23-JAN-82 1300 10 10 rows selected. SQL> select * from dbms_xplan.display_curs或者(); PLAN_TABLE_OUTPUT --------------------------------------------------------------------------------------- SQL_ID 5ujdsh6ztybn2, child number 0 ------------------------------------- select * from scott.emp 或者der by ename offset 0 rows fetch first 10 rows only Plan hash value: 3291446077 --------------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | --------------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | | | 4 (100)| | |* 1 | VIEW | | 10 | 1070 | 4 (25)| 00:00:01 | |* 2 | WINDOW SORT PUSHED RANK| | 14 | 518 | 4 (25)| 00:00:01 | | 3 | TABLE ACCESS FULL | EMP | 14 | 518 | 3 (0)| 00:00:01 | --------------------------------------------------------------------------------- Predicate Inf或者mation (identified by operation id): --------------------------------------------------- 1 - filter(("from$_subquery$_002"."rowlimit_$$_rownumber"<=10 AND "from$_subquery$_002"."rowlimit_$$_rownumber">0)) 2 - filter(ROW_NUMBER() OVER ( ORDER BY "EMP"."ENAME")<=10)复制
所以查询相当于
select * from ( select e.*, row_number() over ( 或者der by "emp"."ename" ) x from scott.emp e ) where x between 0 and 10复制
每当你有重复,然后分配 “row_number” 到这些重复是任意的,例如,如果我有enames:
棕色
琼斯
琼斯
琼斯
史密斯
然后根据执行计划,我可以得到 * 任何 * 以下排序:
棕色 1
琼斯 2
琼斯 3
琼斯 4
史密斯 5
或者
棕色 1
琼斯 4
琼斯 3
琼斯 2
史密斯 5
或者
棕色 1
琼斯 2
琼斯 4
琼斯 3
史密斯 5
etc etc...This is the same with *any* 或者der by clause by the way. The only way to ensure deterministic results is to 或者der by something that does not have duplicates. The easiest way is to use something unique as a tie-breaker, eg
SQL> select * from scott.emp 2 或者der by ename, empno <=== primary key added as tie-breaker 3 offset 0 rows fetch first 10 rows only;复制
文章转载自ASKTOM,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。
评论
相关阅读
Oracle DataGuard高可用性解决方案详解
孙莹
556次阅读
2025-03-26 23:27:33
Oracle RAC 一键安装翻车?手把手教你如何排错!
Lucifer三思而后行
516次阅读
2025-04-15 17:24:06
XTTS跨版本迁移升级方案(11g to 19c RAC for Linux)
zwtian
420次阅读
2025-04-08 09:12:48
墨天轮个人数说知识点合集
JiekeXu
420次阅读
2025-04-01 15:56:03
【纯干货】Oracle 19C RU 19.27 发布,如何快速升级和安装?
Lucifer三思而后行
419次阅读
2025-04-18 14:18:38
Oracle SQL 执行计划分析与优化指南
Digital Observer
416次阅读
2025-04-01 11:08:44
Oracle数据库一键巡检并生成HTML结果,免费脚本速来下载!
陈举超
380次阅读
2025-04-20 10:07:02
Oracle 19c RAC更换IP实战,运维必看!
szrsu
360次阅读
2025-04-08 23:57:08
【活动】分享你的压箱底干货文档,三篇解锁进阶奖励!
墨天轮编辑部
335次阅读
2025-04-17 17:02:24
oracle定时任务常用攻略
virvle
325次阅读
2025-03-25 16:05:19