【问题标题】:Oracle rownum < [n] alternatives? Understanding Of?Oracle rownum < [n] 替代方案?对此事的认知?
【发布时间】:2012-05-30 09:22:52
【问题描述】:

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

想象一下“jones”、“whites”、“browns”可能会卷土重来。我想带回不超过 200 条记录,有没有更好的方法来代替使用 rownum?我对何时应用 rownum 的理解是否正确?

【问题讨论】:

    标签: sql oracle


    【解决方案1】:
    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

    其实这里需要嵌套查询,因为ROWNUMORDER BY之前求值。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多