【发布时间】:2017-05-12 02:37:50
【问题描述】:
我有一个针对所有常见问题解答和 HowTos 建议的 Oracle 数据库的规范 top-N 查询:
select ... from (
select ... from ... order by ...
) where ronwum <= N
它在 Oracle 11 上完美运行,即它按照内部选择中指定的顺序返回前 N 条记录。
但它在 Oracle 12 上中断。它仍然返回相同的前 N 条记录,但它们可能会被打乱。这些记录的最终顺序是不确定的。
我用谷歌搜索,但没有找到任何相关的讨论。看起来其他人总是从这样的选择中获得正确的记录顺序。
但有一个发现很有趣。我看到有些人在外部选择中使用(不幸的是没有解释)一个额外的order by rownum 子句:
select ... from (
select ... from ... order by ...
) where ronwum <= N
order by rownum
(这里的两个rownum都是对Oracle伪列的引用;它不是内部选择返回的东西)
它似乎工作。但是使用 Oracle 优化器,您永远无法确定这只是运气还是真正正确的解决方案。
问题是:order by rownum 在这种情况下是否保证正确排序,为什么?我和我的同事无法就此达成一致。
附:我知道选择前 N 条记录的其他方法,例如使用 Oracle 12 中引入的 row_number 分析函数和 fetch first 子句。我也知道我可以在外部选择上重复相同的 order by ...。问题仅与order by rownum 相关——它是否正确。
【问题讨论】:
-
我认为您需要在内部选择中将
rownum重命名为不同的名称,否则外部引用引用外部查询的rownum,而不是内部查询的rownum。 -
正确的方法是在外部查询中按照与子查询中相同的表达式进行排序。即使在 Oracle 11 和之前的版本中,从内部查询到外部查询的顺序被保留这一事实也是一种实现意外 - SQL 标准无法保证。