2015-07-02 35 views
0

我有以下SQL我試圖對Oracle數據庫運行:的Oracle SQL:通過過濾不ROWNUM返回結果時,它應該

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萬條。

任何幫助將不勝感激。

回答

3

你不能像這樣使用rownumrownum是在實際從查詢返回值時計算的 - 僅當返回一行時才計算。因此,聲明:

where rownum = 2 

永遠不會返回值,因爲在「2」之前需要是「1」。

如果您使用的是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

的原因是因爲你在最外層查詢使用ROWNUM,以及你希望它返回行如果你指定那個rownum> = <某些號碼>。唯一能夠滿足這個條件的數字是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)); 
+0

好,介紹一個問題然後。據我瞭解,如果我將ROWNUM放入子查詢中,它將失序,因爲它將在ORDER BY語句之前應用。在這個宏偉的計劃中,至少在這種情況下,我可以忍受,但爲了找到核心負責人,我將如何處理(在Oracle 11中)通過有序(因此不重疊)的行塊,以便我可以將查詢結果導出到Excel而不超出行限制? – JMichael

+0

是的,對不起 - 我迷惑了自己:-) Rownum在*過濾之後應用*,* *在訂購之前應用。咄。在外部查詢過濾別名rownum列之前,您需要額外的子查詢來執行排序,然後應用rownum。我會更新我的答案,但基本上如果我是你,我會用Gordon的row_number()(根據Request_ID,Actual_Start_Date排序)作爲rn'建議,這意味着你不需要任何額外的子查詢,你可以擺脫順序的條款。 – Boneist