查询SQL中具有重叠时间段的记录 - 单个表

时间:2013-11-22 18:46:38

标签: sql-server date duplicates overlapping

我的问题与此主题中的问题非常相似。但是,我只有一个带字段的表 ID Eff_Date End_Date。它实际上是一个包含更多字段的更大的表,但我刚刚列出了与此相关的那些。

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 个答案:

答案 0 :(得分: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

答案 1 :(得分: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)

UPDATE:实现了我的JOIN限制,其中t1.DEFF&lt; = t2.DEFF意味着t1永远不会在t2内。 Where子句可以简化为单一检查(例如,确保t1在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

答案 2 :(得分:0)

要查找重叠时段,您只需检查每个有效开始日期是&lt; =其他有效结束日期。

因此,如果您有3个唯一的行,您希望看到它们是否重叠,那么逻辑就是(每个的AND语句。用于确定唯一记录的逻辑将超出下面列出的内容)

P1.BEG&lt; = P2.END P1.BEG&lt; = P3.END

P2.BEG&lt; = P1.END P2.BEG&lt; = P3.END

P3.BEG&lt; = P1.END P3.BEG&lt; = P2.END

如果您采用相同的方案,但不是所有3行都必须存在,但是如果它们确实需要选择重叠时段,那么您可以对每个表条件使用左连接并使用每个COALESCE函数

等部分

P1.BEG&lt; = COALESCE(P2.END,'2999-12-31') 这意味着使用P2.END,如果它存在,否则使用2999-12-31,它应该始终使该语句为真。因此,您可以选取所有历史记录(根据您的其他条件),但您会根据重叠时段将不同的行组合在一起。