使用 Window 函数的 Oracle 查询
Oracle query using Window function
请假设我有一个名为 MYDATA 的 Oracle table,具有以下内容:
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
如您所见,table MYDATA 加入自身,用'S' 标记重叠的记录。
我知道当 table 加入自身时,可以使用 Oracle windows 函数重写相应的查询。
最后,使用 Oracle Window 函数重写的查询如下:
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;
你能帮我重写避免自连接的查询吗?
非常感谢您考虑我的请求。
您可以将 case
与 lead
和 lag
一起使用:
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
请假设我有一个名为 MYDATA 的 Oracle table,具有以下内容:
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
如您所见,table MYDATA 加入自身,用'S' 标记重叠的记录。 我知道当 table 加入自身时,可以使用 Oracle windows 函数重写相应的查询。
最后,使用 Oracle Window 函数重写的查询如下:
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;
你能帮我重写避免自连接的查询吗?
非常感谢您考虑我的请求。
您可以将 case
与 lead
和 lag
一起使用:
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