请选择Oracle Select查询帮助

时间:2011-07-21 14:51:19

标签: sql select oracle11g

SELECT  id
      FROM    ( 
 SELECT  id
      FROM   table      
      WHERE   
      PROCS_DT is null
      ORDER BY prty desc, cret_dt ) where rownum >0 and rownum <=100 

上述查询按预期返回100条记录

 SELECT  id
          FROM    ( 
     SELECT  id
          FROM   table      
          WHERE   
          PROCS_DT is null
          ORDER BY prty desc, cret_dt ) where rownum >101 and rownum <=200 

为什么上面的查询会返回零记录?

有人可以帮助我如何继续。我在甲骨文中愚蠢......

2 个答案:

答案 0 :(得分:3)

试试这个:

SELECT id
FROM
  (SELECT id,
          rownum AS rn
   FROM
     (SELECT id
      FROM TABLE
      WHERE PROCS_DT IS NULL
      ORDER BY prty DESC, cret_dt) )
WHERE rn >101
  AND rn <=200

如果您习惯使用ANALYTIC功能,请尝试以下操作:

SELECT id
  FROM 
    (
        SELECT id,
                ROW_NUMBER() OVER(ORDER BY prty DESC, cret_dt ) rn
            FROM table
        WHERE procs_dt IS NULL
    )
 WHERE rn >101 and rn <=200  

答案 1 :(得分:3)

当从查询(或子查询)返回时,将ROWNUM值分配给行。如果未返回行,则根本不会为其分配ROWNUM值;因此返回的ROWNUM值始终从1开始,每行增加1。

(请注意,这些值是在ORDER BY子句指示的任何排序之前分配的。这就是为什么在您的情况下需要检查子查询外的rownum。)

您必须了解的奇怪逻辑是,当您在ROWNUM上有谓词时,您将过滤一个仅在行通过过滤器时才存在的值。从概念上讲,Oracle首先在查询中应用任何其他过滤器,然后暂时将ROWNUM 1分配给第一个匹配的行,并将其与ROWNUM上的过滤器进行对比。如果它通过了这个检查,它将返回该ROWNUM值,下一行将暂时分配给ROWNUM 2.但是如果它没有通过检查,则该行被丢弃,并且暂时将相同的ROWNUM值分配给下一行。

因此,如果ROWNUM上的过滤器不接受值1,则任何行都不会通过过滤器。

使用其他答案中显示的分析函数ROW_NUMBER()是解决此问题的一种方法。此函数根据给定的顺序显式指定行号(与ROWNUM不同)。但是,这可以显着改变性能,因为优化器不一定意识到它可以避免为可能的行分配数字以完成查询。

传统的基于ROWNUM的做法是:

SELECT  id
          FROM    (
  SELECT rownum rn, id
    FROM (
     SELECT  id
          FROM   table      
          WHERE   
          PROCS_DT is null
          ORDER BY prty desc, cret_dt
     ) where rownum <=200
  ) where rn > 101

最里面的查询在概念上找到所有匹配的行并对它们进行排序。下一层为这些分配ROWNUM,并仅返回前200个匹配。 (实际上,Oracle优化器理解排序后跟ROWNUM过滤器的重要性,并且通常会以识别前200行的方式进行排序,而不关心其他行的特定顺序。)

中间层还获取它指定的ROWNUM,并将其作为结果集的一部分返回,并使用别名“rn”。这允许最外层过滤该值以建立下限。

我会尝试使用此变体和分析函数来查看哪种情况在您的情况下表现更好。