大多数数据库都非常清楚以下事实:ORDER BY
子查询中的an 是:
- 不允许:例如SQL Server,Sybase SQL Anywhere(除非以
TOP
或补充OFFSET .. FETCH
)
- 毫无意义:例如PostgreSQL,DB2(再次,除非用
OFFSET .. FETCH
或补充LIMIT
)
这是DB2 LUW手册中的一个示例(重点是我的)
子选择中的ORDER BY子句不会影响查询返回的行的顺序。如果在最外面的全查询中指定了ORDER BY子句,则仅影响返回的行的顺序。
措辞非常明确,就像PostgreSQL的一样:
如果未选择排序,则将以未指定的顺序返回行。在这种情况下,实际顺序将取决于扫描和联接计划的类型以及磁盘上的顺序,但一定不能依赖它。只有明确选择了排序步骤,才能保证特定的输出顺序。
根据此规范,可以得出结论ORDER BY
,派生表中的子句所产生的任何排序都是偶然的,并且可能恰好符合您的预期排序(在您的琐碎示例中,大多数数据库都这样做),但是依靠它是不明智的这个。
关于DB2的旁注:
特别是,DB2具有一个鲜为人知的功能,称为ORDER BY ORDER OF <table-designator>
,可以按如下方式使用:
SELECT C1 FROM
(SELECT C1 FROM T1
UNION
SELECT C1 FROM T2
ORDER BY C1 ) AS UTABLE
ORDER BY ORDER OF UTABLE
在这种特殊情况下,派生表的顺序可以在最外面的SELECT中显式重用
关于Oracle的旁注:
多年来,Oracle一直在实践中OFFSET
使用分页来实现分页ROWNUM
,只有在对派生表进行排序之后才能合理地计算分页:
SELECT *
FROM (
SELECT rownum AS rn, t.* -- ROWNUM here depends on the derived table's ordering
FROM (
SELECT * FROM table ORDER BY time DESC
) t
) t
WHERE rn BETWEEN 10 AND 20
可以合理地预期,至少在存在ROWNUM
查询的情况下,将来的Oracle版本不会破坏此行为,以便不会破坏几乎所有的旧版Oracle SQL,而这些旧版SQL尚未迁移到更理想的版本。可读的SQL标准OFFSET .. FETCH
语法:
SELECT * FROM table ORDER BY time DESC OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY