Oracle SQL:按ROWNUM过滤不应返回结果

时间:2015-07-02 13:36:46

标签: sql oracle

我有以下SQL我正在尝试针对Oracle数据库运行:

SELECT *
FROM(SELECT crd.Request_ID,
        crd.Requested_Start_Date Scheduled_Start,
        crd.Actual_Start_Date Start_Date,
        crd.Actual_Completion_Date Finish_Date,
        crd.Status_Code
    FROM ((SELECT fcr.Request_ID,
                fcr.Requested_Start_Date,
                fcr.Actual_Start_Date,
                fcr.Actual_Completion_Date,
                fcr.Status_Code,
                fcr.Oracle_Session_ID,
                fcr.Responsibility_ID
            FROM Applsys.FND_Concurrent_Requests fcr
            WHERE fcr.Oracle_Session_ID IS NOT NULL)
        UNION ALL (SELECT xcr.Request_ID,
                xcr.Requested_Start_Date,
                xcr.Actual_Start_Date,
                xcr.Actual_Completion_Date,
                xcr.Status_Code,
                xcr.Oracle_Session_ID,
                xcr.Responsibility_ID
            FROM xxfnd.emr_FND_Concurrent_Requests xcr
            WHERE xcr.Oracle_Session_ID IS NOT NULL)) crd
    WHERE crd.Actual_Start_Date >= to_Date('06/01/2014', 'MM/DD/YYYY')
    ORDER BY 3, 1)
WHERE Rownum < (1000000 * to_Number(:X))
    AND ROWNUM >= (1000000 * (to_Number(:X)-1))

如果:X设置为1,我会得到(正如预期的)前999,999行数据。但是,当我将:X设置为2时,不会返回任何内容。尽管事实上当我使用Select Count(*)代替Select *并完全删除Where子句时,结果表明子查询返回的记录超过900万条。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:3)

您不能像这样使用rownum。当从查询实际返回值时计算rownum - 仅在返回行时计算。因此,声明:

where rownum = 2

永远不会返回一个值,因为需要一个&#34; 1&#34;在&#34; 2&#34;之前。

如果您使用的是Oracle 12+,则可以将offset子句与fetch first <n> rows only一起使用。在早期版本中,您可以使用row_number() over ()将行号计算为列,并在where中使用该行。

实际上,您的查询已使用子查询,因此您可以执行以下操作:

select *
from (select . . .,
             row_number() over (order by Request_ID, Actual_Start_Date) as rn
      . . .
     ) t
WHERE rn < (1000000 * to_Number(:X) and)
      rn >= (1000000 * (to_Number(:X)-1))

答案 1 :(得分:1)

原因是因为你在最外面的查询中使用rownum,如果你指定rownum&gt; =&lt; some number&gt;,你期望它返回行。唯一能满足该条件的数字是1,因为rownum是在返回行时动态分配的。

您需要做的是在主子查询中分配rownum并为其指定别名,然后引用外部查询中的别名 - 如下所示:

with main_results as (SELECT crd.Request_ID,
                             crd.Requested_Start_Date Scheduled_Start,
                             crd.Actual_Start_Date Start_Date,
                             crd.Actual_Completion_Date Finish_Date,
                             crd.Status_Code
                      FROM   (SELECT fcr.Request_ID,
                                     fcr.Requested_Start_Date,
                                     fcr.Actual_Start_Date,
                                     fcr.Actual_Completion_Date,
                                     fcr.Status_Code,
                                     fcr.Oracle_Session_ID,
                                     fcr.Responsibility_ID
                              FROM   Applsys.FND_Concurrent_Requests fcr
                              WHERE  fcr.Oracle_Session_ID IS NOT NULL
                              UNION ALL 
                              SELECT xcr.Request_ID,
                                     xcr.Requested_Start_Date,
                                     xcr.Actual_Start_Date,
                                     xcr.Actual_Completion_Date,
                                     xcr.Status_Code,
                                     xcr.Oracle_Session_ID,
                                     xcr.Responsibility_ID
                              FROM   xxfnd.emr_FND_Concurrent_Requests xcr
                              WHERE  xcr.Oracle_Session_ID IS NOT NULL) crd
                      WHERE  crd.Actual_Start_Date >= to_Date('06/01/2014', 'MM/DD/YYYY')
                      ORDER BY 3, 1)
SELECT *
FROM   (select Request_ID,
               Requested_Start_Date Scheduled_Start,
               Actual_Start_Date Start_Date,
               Actual_Completion_Date Finish_Date,
               Status_Code,
               rownum rn
        from   main_results)      
WHERE  rn < (1000000 * to_Number(:X))
AND    rn >= (1000000 * (to_Number(:X)-1));