【问题标题】:order by rownum — is it correct or not?按 rownum 排序 — 是否正确?
【发布时间】: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 标准无法保证。

标签: oracle rownum top-n


【解决方案1】:

内部查询和外部查询可能会或可能不会给出不同的顺序,因此 rownum 的顺序也不同。由于 rownum 已经排序,如果您想获得前 N 条记录,那么最好的办法是在内部查询中创建 rownum 的别名并在外部查询中使用它。

选择 ... 从 ( 从 ... 中选择 rownum rn ... ) 其中 rn

【讨论】:

  • 那行不通,因为 rownum 是在订购之前分配的。该查询将给出 N 个完全随机的行。重写查询并不是问题的重点。
猜你喜欢
  • 1970-01-01
  • 2020-11-20
  • 1970-01-01
  • 1970-01-01
  • 2017-04-12
  • 2021-11-25
  • 1970-01-01
  • 2011-10-15
  • 1970-01-01
相关资源
最近更新 更多