【问题标题】:Mystery of rownum in oracleoracle中rownum之谜
【发布时间】:2015-10-06 07:41:41
【问题描述】:

我正在努力获取基于 rownum 的数据。当我执行以下查询以获取基于 rownum 1 to 4 的结果时,它工作正常。

  SELECT ROWNUM TOTAL,MI.* FROM (SELECT USER_ID,CUSTOMER_NAME FROM ELEC_AUTO_MERC 
  ORDER BY CREATION_DATE DESC ) MI WHERE ROWNUM BETWEEN 1 AND 4;

但是当我执行相同的查询以从 rownum 2 to 4 获取结果时,它不工作,它不返回任何内容。

  SELECT ROWNUM TOTAL,MI.* FROM (SELECT USER_ID,CUSTOMER_NAME FROM ELEC_AUTO_MERC 
  ORDER BY CREATION_DATE DESC ) MI WHERE ROWNUM BETWEEN 2 AND 4;

作为一种解决方法,当我再使用一个 SELECT 语句时,它工作正常,但我认为仅对 rownum 多次使用 SELECT 不是一个好方法。

SELECT * FROM (SELECT ROWNUM TOTAL,MI.* FROM (SELECT USER_ID,CUSTOMER_NAME FROM ELEC_AUTO_MERC 
  ORDER BY CREATION_DATE DESC ) MI) WHERE TOTAL BETWEEN 2 AND 4;

你能帮我创建优化查询吗?

【问题讨论】:

    标签: oracle oracle11g


    【解决方案1】:

    ROWNUM 很奇怪,因为它可以作为查询条件的一部分进行评估 - 但是如果该行随后未能通过该过滤器,则分配给它的 ROWNUM 值可以再次用于下一行。

    这样做的一个重要影响是,如果您使用任何排除 ROWNUM 值 1 的条件,您将永远无法获得匹配。针对此条件进行测试的第一行将是第 1 行;但随后它将无法通过测试,因此下一行将被视为第 1 行;等等。

    所以你的条件ROWNUM BETWEEN 2 AND 4 永远不会是真的。

    您找到的解决方法是传统的解决方法。另一种方法是使用分析函数对行进行排名,然后根据排名进行过滤,例如:

    SELECT MI.* FROM (
      SELECT USER_ID,CUSTOMER_NAME, RANK() OVER (ORDER BY CREATION_DATE DESC) AS the_rank
      FROM ELEC_AUTO_MERC 
      ) MI
    WHERE the_rank BETWEEN 2 AND 4;
    

    几个分析函数 - RANK、DENSE_RANK 和 ROW_NUMBER - 可用于此目的,并且会产生略有不同的结果,尤其是在存在平局的情况下。查看文档。

    【讨论】:

      猜你喜欢
      • 2012-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-24
      • 1970-01-01
      • 2014-04-05
      • 2012-09-09
      • 1970-01-01
      相关资源
      最近更新 更多