2013-02-11 42 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