SELECT *
FROM (
SELECT *
FROM mytable
WHERE lastname = 'Jones'
ORDER BY
id
)
WHERE rownum <= 200
或
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY id) rn
FROM mytable
WHERE lastname = 'Jones'
)
WHERE rn <= 200
后者在9i 中速度较慢,但在10g+ 中的工作原理相同。
据我了解,rownum 被查询后应用于整个结果集
没有。只要满足WHERE 子句的每条记录被提取(但在它们被排序之前),就会应用rownum。
其实这里需要嵌套查询,因为ROWNUM在ORDER BY之前求值。
ROWNUM 和 ROW_NUMBER() 都需要优化。如果您在(lastname, id) 上有索引,则查询将使用该索引并在返回第 200 条记录后停止(您将在计划中看到COUNT(STOPKEY))。
ROWNUM 和分页还有一个共同的警告。这个查询:
SELECT *
FROM (
SELECT *
FROM mytable
WHERE lastname = 'Jones'
ORDER BY
id
)
WHERE rownum BETWEEN 201 AND 400
永远不会返回任何东西,因为ROWNUM 本身就是WHERE 条件的一部分。引擎无法返回第一行,因为它的 ROWNUM = 1 不满足 WHERE 子句。
要解决这个问题,您必须双重嵌套查询:
SELECT *
FROM (
SELECT q.*, ROWNUM AS rn
FROM (
SELECT *
FROM mytable
WHERE lastname = 'Jones'
ORDER BY
id
) q
)
WHERE rn BETWEEN 201 AND 400
这也将优化为COUNT(STOPKEY)。