据我了解,rownum 在查询后应用于整个结果集。这意味着如果我想使用 rownum 限制结果,它仍然会首先查询所有内容。我有一个包含十万条记录的用户表。我也在开发一个网站来搜索这个表并返回一个结果集。不幸的是,请求者希望我包含仅搜索姓氏的功能。
想象一下可能会回来的“琼斯”、“白人”、“布朗”。我想带回不超过 200 条记录,有没有更好的方法来代替使用 rownum?我对何时应用 rownum 的理解是否正确?
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 在查询后应用于整个结果集
rownum
不会。只要满足该子句的每条记录被WHERE
提取(但在它们被排序之前),就会应用。
实际上,这里需要嵌套查询,因为ROWNUM
在ORDER BY
.
两者ROWNUM
和ROW_NUMBER()
都需要优化。如果您在 上有一个索引(lastname, id)
,则查询将使用该索引并在返回第 200 条记录后停止(您将COUNT(STOPKEY)
在计划中看到 a )。
还有一个常见的警告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
这也将优化为a COUNT(STOPKEY)
。