3

据我了解,rownum 在查询后应用于整个结果集。这意味着如果我想使用 rownum 限制结果,它仍然会首先查询所有内容。我有一个包含十万条记录的用户表。我也在开发一个网站来搜索这个表并返回一个结果集。不幸的是,请求者希望我包含仅搜索姓氏的功能。

想象一下可能会回来的“琼斯”、“白人”、“布朗”。我想带回不超过 200 条记录,有没有更好的方法来代替使用 rownum?我对何时应用 rownum 的理解是否正确?

4

1 回答 1

9
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提取(但在它们被排序之前),就会应用。

实际上,这里需要嵌套查询,因为ROWNUMORDER BY.

两者ROWNUMROW_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)

于 2012-05-23T19:29:44.997 回答