在同一个SQL表中请求重叠的日期范围

问题描述 投票:0回答:2

我在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
sql oracle
2个回答
1
投票

您可以使用LAGLEAD分析函数,然后您不需要使用任何自连接:

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


0
投票

在最简单的形式中,这使得表格中的所有内容在另一条线路终止之前开始,其中齿轮和车辆使用简单的自连接相同:

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
© www.soinside.com 2019 - 2024. All rights reserved.