2013-02-11 29 views
4

如何在Oracle中執行相關子查詢,該查詢返回基於ORDER BY子句的第一個匹配行?我試圖從SQL Server翻譯這樣做的查詢。翻譯回到頂端從SQL Server到Oracle的1個相關子查詢

爲了記錄,我需要堅持(主要)SQL-92語法。分析函數根本不應該使用,我需要儘量減少使用非標準SQL。 TOP 1 ... ORDER BY是SQL Server專有的,我很努力將它翻譯成rownum

注:有人指出,這個特定的查詢不需要TOP/LIMIT/rownum,因爲它在語義上等同於使用Min(),因爲我們只需要一列。但我仍然會欣賞並獎勵任何關於如何進行翻譯的幫助 - 因爲我希望更好地學習Oracle。

這裏的SQL Server查詢(和SqlFiddle for it):

SELECT 
    D.StartDate, 
    (
    SELECT TOP 1 E.EndDate 
    FROM dbo.Dates E 
    WHERE 
     E.EndDate >= D.EndDate 
     AND NOT EXISTS (
     SELECT * 
     FROM dbo.Dates E2 
     WHERE 
      E.StartDate < E2.StartDate 
      AND E.EndDate > E2.StartDate 
    ) 
    ORDER BY 
     E.EndDate, 
     E.StartDate DESC 
) EndDate 
FROM 
    dbo.Dates D 
WHERE 
    NOT EXISTS (
    SELECT * 
    FROM dbo.Dates D2 
    WHERE 
     D.StartDate < D2.EndDate 
     AND D.EndDate > D2.EndDate 
); 

這是我已經試過。我受阻,因爲我在D.EndDate外部參考上遇到錯誤。

ORA-00904: 「d」 「ENDDATE」:無效的標識符

但什麼問題? SELECT子句中的相關子查詢應該可以訪問所有外部表數據。我不知道下一步該去哪裏。 (和the SqlFiddle for this)。

SELECT 
    D.StartDate, 
    (
    SELECT * 
    FROM (
     SELECT E.EndDate 
     FROM Dates E 
     WHERE 
     E.EndDate >= D.EndDate 
     AND NOT EXISTS (
      SELECT * 
      FROM Dates E2 
      WHERE 
      E.StartDate < E2.StartDate 
      AND E.EndDate > E2.StartDate 
     ) 
     ORDER BY 
     E.EndDate, 
     E.StartDate DESC 
    ) 
    WHERE rownum = 1 
) EndDate 
FROM 
    Dates D 
WHERE 
    NOT EXISTS (
    SELECT * 
    FROM Dates D2 
    WHERE 
     D.StartDate < D2.EndDate 
     AND D.EndDate > D2.EndDate 
); 
+0

在[本文](http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:1853075500346799932)中,Tom說:「ANSI SQL有表引用(相關名稱)的範圍僅限於一個級別「(我不知道如何解決您的問題,對不起)。 – Mat 2013-02-11 08:50:57

+0

你爲什麼試圖避免分析功能? – 2013-02-11 09:29:15

+0

@Chris是否重要?這是我必須解決的問題。 – ErikE 2013-02-11 09:33:48

回答

1

我可能失去了一些東西,但你能不能用MIN代替TOP 1 ... ORDER BY,因爲你是結束日期,起始日期遞減排序,只有選擇結束日期,開始日期是不相關的排序,它是隻有當你有一個是相同的2個結束日期考慮,但因爲你只選擇結束日期也不要緊其中兩個(或多個結束日期)的使用:

SELECT D.StartDate, 
     ( SELECT MIN(E.EndDate) 
      FROM Dates E 
      WHERE E.EndDate >= D.EndDate 
      AND  NOT EXISTS 
        ( SELECT 1 
         FROM Dates E2 
         WHERE E.StartDate < E2.StartDate 
         AND  E.EndDate > E2.StartDate 
        ) 
     ) EndDate 
FROM Dates D 
WHERE NOT EXISTS 
     ( SELECT 1 
      FROM Dates D2 
      WHERE D.StartDate < D2.EndDate 
      AND  D.EndDate > D2.EndDate 
     ); 

Example on SQL Fiddle

+0

你是對的。我只能懇求它已經過了午夜...... :)對於相等結束日期,StartDate的問題對於「NOT EXISTS」E2部分來說很重要。事實上,我仍然不確定我是否100%正確......但無論如何,謝謝你看到這個特殊的問題。在任何情況下,如何在Oracle中完成這種類型的相關子查詢? – ErikE 2013-02-11 19:58:30

+0

如果不使用分析功能,我無法做到這一點,儘管我從來沒有真正與Oracle合作過,所以我可能會丟失一些技巧。這是我放棄之前得到的... http://sqlfiddle.com/#!4/2e766/40 – GarethD 2013-02-11 20:44:40