Oracle查询使用Window函数

时间:2015-02-24 14:40:26

标签: oracle function window

请假设我有一个名为MYDATA的Oracle表,其中包含以下内容:

NAME,    D1,         D2
A,       01/01/2010, 02/03/2010
B,       03/03/2010, 20/03/2010
C,       10/03/2010, 20/09/2010
D,       10/12/2010, 31/12/2010


Insert into MYDATA
   (NAME, D1, D2)
 Values
   ('A', TO_DATE('01/01/2010 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('03/02/2010 00:00:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into MYDATA
   (NAME, D1, D2)
 Values
   ('B', TO_DATE('03/03/2010 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('03/20/2010 00:00:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into MYDATA
   (NAME, D1, D2)
 Values
   ('C', TO_DATE('03/10/2010 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('09/20/2010 00:00:00', 'MM/DD/YYYY HH24:MI:SS'));
Insert into MYDATA
   (NAME, D1, D2)
 Values
   ('D', TO_DATE('12/10/2010 00:00:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE('12/31/2010 00:00:00', 'MM/DD/YYYY HH24:MI:SS'));
COMMIT;

我想用' S'具有重叠间隔的记录:在这种情况下,记录B和记录C重叠。

我编写了以下Oracle查询:

  SELECT   name, D1, D2, WMSYS.WM_CONCAT (OVERLAPPING)
    FROM   (SELECT   T1.name, T1.D1, T1.D2, NULL OVERLAPPING
              FROM   MYDATA T1, MYDATA T2
             WHERE   NOT ( (T1.D1, T1.D2) OVERLAPS (T2.D1, T2.D2))
                     AND T1.NAME <> T2.NAME
            UNION
            SELECT   T1.name, T1.D1, T1.D2, 'S'
              FROM   MYDATA T1, MYDATA T2
             WHERE   ( (T1.D1, T1.D2) OVERLAPS (T2.D1, T2.D2))
                     AND T1.NAME <> T2.NAME)
GROUP BY   NAME, D1, D2;

结果是:

NAME, D1,         D2,         WMSYS.WM_CONCAT(OVERLAPPING)
A,    01/01/2010, 02/03/2010, NULL
B,    03/03/2010, 20/03/2010, S
C,    10/03/2010, 20/09/2010, S
D,    10/12/2010, 31/12/2010, NULL

正如您所看到的,MYDATA表连接在一起,标有&#39; S&#39;重叠的记录。 我知道当一个表加入时,可以使用Oracle窗口函数重写相应的查询。

最后,使用Oracle Window Functions重写的查询如下:

  SELECT   NAME,
           D1,
           D2
    FROM   (SELECT   T1.NAME,
                     T1.D1,
                     T1.D2
              FROM   MYDATA T1, MYDATA T2
             WHERE   ( (T1.D1, T1.D2) OVERLAPS (T2.D1, T2.D2))
                     AND T1.NAME <> T2.NAME)
GROUP BY   NAME, D1, D2;

请问我帮助重写查询以避免自我加入?

非常感谢您考虑我的要求。

1 个答案:

答案 0 :(得分:2)

您可以将caseleadlag

一起使用
SELECT   D.*,
         CASE
            WHEN LAG (D1) OVER (ORDER BY D1) IS NOT NULL
                 AND (LAG (D1) OVER (ORDER BY D1), LAG (D2) OVER (ORDER BY D1))
                       OVERLAPS (D1, D2)
                 OR LEAD (D1) OVER (ORDER BY D1) IS NOT NULL
                   AND (LEAD (D1) OVER (ORDER BY D1),
                        LEAD (D2) OVER (ORDER BY D1))
                         OVERLAPS (D1, D2)
            THEN
               'S'
            ELSE
               'N'
         END
            OVERLAP
  FROM   MYDATA D;

结果:

NAME                                               D1        D2        OVERLAP
-------------------------------------------------- --------- --------- -------
A                                                  01-JAN-10 02-MAR-10 N      
B                                                  03-MAR-10 20-MAR-10 S      
C                                                  10-MAR-10 20-SEP-10 S      
D                                                  10-DEC-10 31-DEC-10 N