2013-11-22 46 views
0

我的问题与此主题中的问题非常相似。不过,我只有1个表,其中的字段为 ID Eff_Date End_Date。它实际上是一个更大的表格,有更多的字段,但我只列出了与这里相关的那些表格。在SQL中查询重叠时间段的记录 - 单表

What is a simple and efficient way to find rows with time-interval overlaps in SQL?

我需要写一个SQL语句来获取该有重叠的生效日期期间相同的ID记录。有效的记录通常以end_date为'99991231'。

select ID, DEFF, DEND 
from table1 
where ID in (
     select ID 
     from table1 
     where DEND = 99991231 
     group by ID 
     having COUNT(*) >1) 
and DEND = 99991231 
order by 1,2 

任何想法都会有帮助!

回答

3
SELECT 
    t1.ID, t1.DEFF, t1.DEND, t2.DEFF, t2.DEND 
FROM table1 t1 
INNER JOIN table1 t2 ON (t2.ID = t1.ID AND t2.MyUniqueRowId > t1.MyUniqueRowId) 
WHERE t1.DEND >= t2.DEFF 
    AND t2.DEND >= t1.DEFF 
+0

我的理解是,你会想在t2.ID = t1.ID上做这样的连接,因为根据以下问题,ID不是唯一的:“获取具有重叠的相同ID的记录” –

+0

编辑的查询现在有很多误报......它也会有重复。现在有一个新的编辑:) –

+0

很确定这不是必要的'AND t2.DEND> = t1.DEFF' –

0

未经测试,我相信下面会给你正确的答案,没有重复(把戏删除重复是确保t1.DEFF < = t2.DEFF总是):

SELECT t1.ID, 
     t1.DEFF AS DEFF1, t1.DEND AS DEND1 
     t2.DEFF AS DEFF2, t2.DEND AS DEND2 
FROM table1 t1 
    -- exclude yourself in join (assuming that no two entries are identical) 
    INNER JOIN table1 t2 ON t1.ID = t2.ID 
     AND t1.DEFF <= t2.DEFF 
      AND t1.DEFF != t2.DEFF 
      AND t1.DEND != t2.DEND 
WHERE 
     -- check for overlap including t1 fully inside of t2 
     (t1.DEFF BETWEEN t2.DEFF AND t2.DEND 
      OR t1.DEND BETWEEN t2.DEFF AND t2.DEND) 
    OR 
     -- needed to additionally catch t2 fully inside of t1 
     (t2.DEFF BETWEEN t1.DEFF AND t1.DEND 
      OR t2.DEND BETWEEN t1.DEFF AND t1.DEND) 

更新:认识到我的JOIN限制,其中t1.DEFF < = t2.DEFF意味着t1永远不会在t2内。 Where子句然后可以简化为单一的检查(例如,确保T2不启动T1结束前):

SELECT t1.ID, 
     t1.DEFF AS DEFF1, t1.DEND AS DEND1 
     t2.DEFF AS DEFF2, t2.DEND AS DEND2 
FROM table1 t1 
    -- exclude yourself in join (assuming that no two entries are identical) 
    INNER JOIN table1 t2 ON t1.ID = t2.ID 
     AND t1.DEFF <= t2.DEFF 
      AND t1.DEFF != t2.DEFF 
      AND t1.DEND != t2.DEND 
WHERE 
    t2.DEFF <= t1.DEND 
+0

您不需要将一个范围与另一个范围完全重叠作为特殊情况,因为它们不是。如果T2在T1结束之前开始,而T1在T2结束之前开始,则它们重叠,无论它们如何排列。额外的检查是多余的 – Anon

+0

@Anon - 良好的捕获,我原来的查询需要,但我添加JOIN条件使额外的检查不必要的。我已更新查询。 –

0

要找到重叠的时间,你只需要检查每一个有效的开始日期是< =到其他有效结束日期。

所以,如果你有3个,你想看看他们是否重叠的逻辑将是唯一的行(并为每个语句。逻辑来确定唯一的记录将是什么下面列出之外)

P1.BEG < = P2.END P1.BEG < = P3.END

P2.BEG < = P1.END P2.BEG < = P3.END

P3.BEG < = P1.END P3。 BEG < = P2.END

如果你采取同样的情况,但并非所有3行必须存在,但如果他们这样做,你要拿起重叠时期,那么你可以使用左联接为每个表的标准,使用COALESCE函数围绕每个部分如

P1.BEG < = COALESCE(P2.END,“2999年12月31日”) 这意味着使用P2.END如果它存在以其他方式使用2999年12月31日这应该始终使陈述真实。因此,您可以选取所有历史记录(根据您的其他条件),但是您会根据重叠的时间段将不同的行绑定在一起。