2013-11-22 6 views
0

제 질문은이 스레드와 매우 비슷합니다. 그러나 필드가 1 개인 테이블 Eff_Date End_Date 만 있습니다. 실제로 더 많은 필드가있는 더 큰 테이블이지만 여기서는 관련있는 필드를 나열했습니다.SQL - 단일 테이블에서 기간이 겹치는 레코드 쿼리

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

나는 효력 발생 일의 기간이 겹치는 같은 ID가 기록을 가져 오기 위해 SQL 문을 작성해야합니다. 유효한 레코드의 종료일은 일반적으로 '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

편집 된 쿼리는 이제 오 탐지 (false positives)가 많습니다 ... 또한 복제본도 있습니다. 그리고 지금은 새로운 편집이있었습니다 : –

+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 내에있을 수 없다는 것을 의미합니다. 절을 한 후 하나의 검사로 간단하게 할 수있는 (T1이 종료되기 전에 예를 들어, T2가 시작되지 않는지 확인) :

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

하나의 범위를 특수한 경우로 완전히 겹치지 않도록 처리 할 필요가 없습니다. T1이 끝나기 전에 T2가 시작되고 T2가 끝나기 전에 T1이 시작되면 배열이 어 + 게 관계없이 겹칩니다. 여분의 체크는 여분의 것입니다 – Anon

+0

@Anon - 좋은 캐치, 원래의 쿼리가 필요했지만 추가 된 JOIN 조건으로 인해 여분의 체크가 필요 없습니다. 쿼리를 업데이트했습니다. –

0

방금 ​​각각의 효과가 시작 날짜 확인 할 필요가 중복되는 기간을 찾으려면받는 사람 = <입니다 기타 효과적인 종료일.

그래서 당신은 당신이 그들이 논리가 될 겹치는 경우보고 싶어 3 개 독특한 행이 있다면 (AND 각각 문을. 아래 어떤 외부 것이다 독특한 기록을 확인하는 로직)

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

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

P3.BEG < = P1.END P3. BEG < = P22.END

동일한 시나리오를 사용하지만 3 개의 행이 모두 있어야하는 것은 아니지만 겹치는 기간을 선택하려면 각 테이블 조건에 대해 왼쪽 조인을 사용할 수 있습니다.

P1.BEG < = COALESCE (P2.END, '2999-12-31') 이렇게하면 각 부분마다 COALESCE 함수를 사용하십시오. 진술을 항상 사실로 만들어야합니다. 따라서 (다른 기준에 따라) 모든 기록을 선택하지만 겹치는 기간에 따라 다른 행을 함께 묶습니다.

관련 문제