Most sources, including Oracle's own Top-N Queries article, give syntax similar to the following for performing a Top-N query:
SELECT val
FROM (
SELECT val
FROM rownum_order_test
ORDER BY val DESC
)
WHERE ROWNUM <= 5;
This is guaranteed to give the top 5 values; however, is it guaranteed to give them in the correct order? This question, citing Wikipedia, indicates otherwise:
Although some database systems allow the specification of an ORDER BY clause in subselects or view definitions, the presence there has no effect.
Does this mean that the aforementioned code does not guarantee any ordering, and requires an additional ORDER BY
, or is it an exceptional case?
SELECT val
FROM (
SELECT val
FROM rownum_order_test
ORDER BY val DESC
)
WHERE ROWNUM <= 5
ORDER BY val DESC; -- Is this line necessary?
Edit: Assume that the outer query will be executed directly (not nested in another query). I'm posing this question because it feels like a glaring omission that none of the sources (including Oracle's) bothered to mention the need for the ORDER BY
, despite that ordering would be intuitively expected from such top-n queries.
答案 0 :(得分:1)
The order by clearly has an effect here, because if it did not then the query simply would not work to provide the top-n values.
There may well be cases where the optimiser can detect that there is no effect provided by an ORDER BY, and in such cases it might transform the query to remove the ORDER BY, but this is not one of those cases.
If your outer query does not re-order the rows, either explicitly or implicitly (through a join, perhaps), then I would be confident that in this case the order will be preserved.
答案 1 :(得分:1)
在旧版本的ORACLE(8.0)中,您无法在子查询中使用ORDER BY子句。因此,仅对于那些还使用某些古老版本的人而言,还有另一种应对方式:UNION运算符的魔力。 UNION将按查询中的列对记录进行排序:
示例:
SELECT * FROM
(SELECT EMP_NO, EMP_NAME FROM EMP_TABLE
UNION
SELECT 99999999999,'' FROM DUAL)
WHERE ROWNUM<=5;
其中99999999999大于EMP_NO中的所有值
或者,如果您要选择薪水最高的5位薪水最高的5名员工:
SELECT EMP_NO, EMP_NAME, 99999999999999-TMP_EMP_SAL
FROM
(SELECT 99999999999999-EMP_SAL TMP_EMP_SAL, EMP_NO, EMP_NAME
FROM EMP_TABLE
UNION
SELECT 99999999999999,0,'' FROM DUAL)
WHERE ROWNUM<=5;
关于, 维吉尔·伊内斯库(Virgil Ionescu)