我在oracle SQL数据库中有一个表。
它的列是VEHICLE_ID,GEAR_ID,STARTDATE,ENDDATE,AA。
startdate和enddate表示特定车辆的档位内的日期范围。
我的问题是我需要找到具有重叠日期的相同车辆的相同档位。
我提出了这个问题
SELECT DISTINCT G.* FROM VEHICLE_GEARS G JOIN (SELECT A.*, B.CNT FROM VEHICLE_GEARS A JOIN
(SELECT VEHICLE_ID, GEAR_ID, COUNT(GEAR_ID) CNT FROM VEHICLE_GEARS GROUP BY
VEHICLE_ID, GEAR_ID HAVING COUNT(GEAR_ID) > 1) B
ON A.VEHICLE_ID = B.VEHICLE_ID AND A.GEAR_ID = B.GEAR_ID) ASDF ON
G.VEHICLE_ID = ASDF.VEHICLE_ID AND G.GEAR_ID = ASDF.GEAR_ID
WHERE
NOT(
TRUNC(ASDF.STARTDATE) >= TRUNC(G.ENDDATE)
OR
TRUNC(ASDF.ENDDATE) <= TRUNC(G.STARTDATE)
)
ORDER BY 1, 5
问题是,即使是具有相同的齿轮结束日期的齿轮与齿轮的开始日期也是重叠的,我不想要,但即使从where子句中删除相等结果也是相同的。
请提前帮助,谢谢。
编辑:示例数据(在上述查询之后):
000000006 2012-02-20 00:00:00 3 2999-12-31 00:00:00 804
000000006 1991-07-01 00:00:00 9 2999-12-31 00:00:00 804
000000147 1991-07-01 00:00:00 1 1992-10-08 00:00:00 601
000000147 1992-10-08 00:00:00 2 2999-12-31 00:00:00 601
预期的是车辆000000147不应该在结果集中,因为齿轮601的结束日期与其第二“实例”的标准相同。前两个记录(车辆00000006)是正确的,因为齿轮804的日期是重叠的。
样本表数据:
000000000 2014-02-25 00:00:00 1 2999-12-31 00:00:00 302
000000000 2006-12-15 00:00:00 3 2999-12-31 00:00:00 604
000000000 2006-12-15 00:00:00 4 2999-12-31 00:00:00 605
000000006 1991-07-01 00:00:00 1 2999-12-31 00:00:00 601
000000006 2016-01-18 00:00:00 10 2999-12-31 00:00:00 605
000000006 2012-02-20 00:00:00 3 2999-12-31 00:00:00 804
000000006 1991-07-01 00:00:00 9 2999-12-31 00:00:00 804
000000147 1991-07-01 00:00:00 1 1992-10-08 00:00:00 601
000000147 1992-10-08 00:00:00 2 2999-12-31 00:00:00 601
预期成绩:
000000000 2006-12-15 00:00:00 4 2999-12-31 00:00:00 605
000000006 2016-01-18 00:00:00 10 2999-12-31 00:00:00 605
您可以使用LAG
和LEAD
分析函数,然后您不需要使用任何自连接:
Oracle安装程序:
CREATE TABLE VEHICLE_GEARS ( vehicle_id, startdate, enddate, gear_id ) AS
SELECT '000000000', DATE '2014-02-25', DATE '2999-12-31', 302 FROM DUAL UNION ALL -- No duplicate vehicle & gear
SELECT '000000000', DATE '2006-12-15', DATE '2999-12-31', 604 FROM DUAL UNION ALL -- No duplicate vehicle & gear
SELECT '000000000', DATE '2006-12-15', DATE '2999-12-31', 605 FROM DUAL UNION ALL -- No duplicate vehicle & gear
SELECT '000000006', DATE '1991-07-01', DATE '2999-12-31', 601 FROM DUAL UNION ALL -- No duplicate vehicle & gear
SELECT '000000006', DATE '2016-01-18', DATE '2999-12-31', 605 FROM DUAL UNION ALL -- No duplicate vehicle & gear
SELECT '000000006', DATE '2012-02-20', DATE '2999-12-31', 804 FROM DUAL UNION ALL -- Overlaps previous
SELECT '000000006', DATE '1991-07-01', DATE '2999-12-31', 804 FROM DUAL UNION ALL -- Overlaps next
SELECT '000000147', DATE '1991-07-01', DATE '1992-10-08', 601 FROM DUAL UNION ALL -- Same end date as next start date
SELECT '000000147', DATE '1992-10-08', DATE '2999-12-31', 601 FROM DUAL UNION ALL -- Same start date as previous end date
SELECT '000000567', DATE '2018-01-01', DATE '2018-12-31', 203 FROM DUAL UNION ALL -- Overlaps next
SELECT '000000567', DATE '2018-12-01', DATE '2019-01-10', 203 FROM DUAL UNION ALL -- Overlaps previous and next
SELECT '000000567', DATE '2018-12-31', DATE '2019-01-10', 203 FROM DUAL UNION ALL -- Overlaps previous and next
SELECT '000000567', DATE '2018-12-31', DATE '2019-01-31', 203 FROM DUAL UNION ALL -- Overlaps previous
SELECT '000000567', DATE '2019-01-31', DATE '2019-02-28', 203 FROM DUAL -- Same start date as previous
查询:
SELECT vehicle_id,
startdate,
enddate,
gear_id
FROM (
SELECT G.*,
LAG( enddate ) OVER ( PARTITION BY vehicle_id, gear_id ORDER BY startdate, enddate ) AS prev_enddate,
LEAD( startdate ) OVER ( PARTITION BY vehicle_id, gear_id ORDER BY startdate, enddate ) AS next_startdate
FROM VEHICLE_GEARS G
)
WHERE prev_enddate > startdate
AND ( enddate <= next_startdate OR next_startdate IS NULL );
输出:
VEHICLE_ID | STARTDATE | ENDDATE | GEAR_ID :--------- | :-------- | :-------- | ------: 000000006 | 20-FEB-12 | 31-DEC-99 | 804 000000567 | 31-DEC-18 | 31-JAN-19 | 203
db <>小提琴here
在最简单的形式中,这使得表格中的所有内容在另一条线路终止之前开始,其中齿轮和车辆使用简单的自连接相同:
select t1.*, t2.*
from VEHICLE_GEARS t1
inner join VEHICLE_GEARS t2
on t1.gear_id = t2.gear_id
and t1.vehicle_id = t2.vehicle_id
and t2.startdate < t1.enddate
and t1.startdate < t2.startdate