2012-08-09 6 views
3

유효한 세그먼트에있는 시간이있는 이벤트를 반환하는 SQL 쿼리를 실행하는 방법을 알고 싶습니다.하위 쿼리 사이의 SQL

예를 들어, 나는 두 개의 테이블이,

이벤트

event_id event_time 
0  134 
1  434 
2  4300 

세그먼트

segment_type segment_start_time segment_end_time data1 100 130 data1 200 500 data1 700 8000 veto1 400 440 data2 150 450 data2 4000 5000 veto2 175 200 

내가

,112을 반환하는 쿼리를 원하는3210

나는

SELECT * 
FROM event 
WHERE 
    event.event_time > (SELECT segment.segment_start_time FROM segment) 
    AND 
    event.event_time < (SELECT segment.segment_end_time FROM segment) 

같은 것을 생각하지만 이것은 단지 아무 것도 반환하지 않습니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?

내가 원하는 다음 단계는 이벤트 시간을 찾는 것입니다. 는 '데이터'세그먼트 시작 시간과 종료 시간 및 NOT 시간과 종료 시간

을 시작 그리고 마지막으로, 실제로 데이터 세그먼트 및 거부권 세그먼트의 두 가지 유형을 가지고 '거부권'세그먼트 사이

. 나는 시간이있는 사건들을 돌려주고 싶다. 는 'DATA1'세그먼트 사이

는 'veto1'세그먼트 사이에 시간 및 종료 시간과

NOT 시작 시간 및 종료 시간과

을 시작할 'DATA2'세그먼트 사이에 시간 및 종료 시간과

시작

는 'veto2'세그먼트 사이에 위 내 예를 들어 테이블에서

그래서 시간과 종료 시간을 시작하지, 내가 원하는 출력이 될 것

event_id event_time 
2  4300 
+0

다른 세그먼트가 겹치지 않습니까? '이벤트'또는 '세그먼트'에 더 많은 레코드가 있습니까? – MatBailie

+0

어떤 데이터베이스와 버전을 사용하고 있습니까? –

+0

세그먼트가 겹칠 수 있지만 '유형이 다른'세그먼트 만 - 아래 내 의견을 참조하십시오. 나는 SQlite를 사용하고있다. 3.7.13 – ShaunH

답변

5

일반적으로 세그먼트 테이블보다 이벤트 테이블에 더 많은 항목이 있다고 가정합니다.

이렇게하면 pseduo 코드가 "모든 세그먼트에 대해 어떤 이벤트가 유효한지 확인"할 수 있습니다. 이렇게하면 이벤트 테이블에서 범위 검색을 할 수 있습니다. segment 다른 항목이 겹칠 수 있다면

SELECT 
    event.event_id, event.event_time 
FROM 
    segment 
INNER JOIN 
    event 
    ON event.event_time >= segment.segment_start_time 
    AND event.event_time < segment.segment_end_time 
GROUP BY 
    event.event_id, event.event_time 

GROUP BY

만 필요하다.


다른 접근법은 "모든 세그먼트가 중복 여부를 확인, 각 이벤트에 대한"의사 - 코드이다.

그러나 이렇게하면 범위 탐색 (@MarkByers 대답에 대한 내 의견보기)을 허용하지 않습니다.질문하는 편집 다음


편집 ...

나는 변화를 이해

는 지금까지, 이벤트가있는 경우에만 반환해야 ...

  • 이벤트 시간 이내 최소한 (하나의 데이터 1 세그먼트 및 하나의 데이터 2 세그먼트)
  • 이벤트 시간이 당신의 DBMS는 경구가 구현 한 경우 (모든 veto1 세그먼트 또는 어떤 veto2 세그먼트)


SELECT 
    event.event_id, event.event_time 
FROM 
    segment 
INNER JOIN 
    event 
    ON event.event_time >= segment.segment_start_time 
    AND event.event_time < segment.segment_end_time 
GROUP BY 
    event.event_id, event.event_time 
HAVING 
     0 = SUM(CASE WHEN segment_type = 'veto1' THEN 1 ELSE 0 END) 
    AND 0 = SUM(CASE WHEN segment_type = 'veto2' THEN 1 ELSE 0 END) 
    AND 1 = SUM(CASE WHEN segment_type = 'data1' THEN 1 ELSE 0 END) 
    AND 1 = SUM(CASE WHEN segment_type = 'data2' THEN 1 ELSE 0 END) 
+0

감사합니다. @Dems. 이것은 작동하는 것 같습니다. 예, 중복 될 수있는 세그먼트가 있습니다. 그러나 세그먼트 테이블에는 세그먼트가 네 가지로 구분되어 있습니다. data1 및 data2, veto1 및 veto2. 나는 실제로 ((data1-veto1) 교차점 (data2-veto1)에있는 시간을 가진 이벤트를 나열하려고합니다. – ShaunH

+0

@ShaunH -'((data1-veto1) intersection (data2-veto1)) '이 무슨 뜻인지 잘 모르겠습니다. 실제 시나리오를 설명하는 예제 데이터와 원하는 출력으로 질문을 업데이트 할 수 있습니까? – MatBailie

+0

질문을 수정했습니다. 죄송합니다. 복잡하게 들리시는 분도 계시므로, 모든 것을 초기 상태라고 말한 것은 아닙니다. – ShaunH

1

WHERE EXISTS 또는 가입을 사용하십시오.

SELECT event_id, event_time 
FROM event 
WHERE EXISTS 
(
    SELECT * 
    FROM segment 
    WHERE event.event_time BETWEEN segment_start_time AND segment_end_time 
) 
+0

'segment (start, end)'의 인덱스를 가정하면,'start'가'0'에서'event.event_time'까지의 모든 'segment'가'end' 확인했다. 반 카티 션 제품 ... – MatBailie

0

세그먼트가 중복되지 않는 경우, 당신은이를 사용할 수 있습니다 (TOP 또는 LIMIT이든 독점 구문에 적응 OFFSET/FETCH 구문) :

SELECT 
    event_id, event_time 
FROM 
    event AS e 
WHERE 
    event_time < 
    (SELECT 
      s.segment_end_time 
     FROM 
      segment AS s 
     WHERE 
      s.segment_start_time <= e.event_time 
     ORDER BY 
      s.segment_start_time DESC 
     OFFSET 1 ROWS 
     FETCH NEXT 1 ROWS ONLY 
    ) ; 
0

나는 이것이 내가 찾고 있어요 쿼리 생각,하지만 난 100 % 확실하지 않다.

SELECT * 
FROM event 
WHERE EXISTS 
(
    SELECT * 
    FROM segment 
    WHERE (event.time BETWEEN segment.start_time AND segment.end_time 
        AND segment.type IN ("data1", "data2")) 
) AND EXISTS 
(
    SELECT * 
    FROM segment 
    WHERE (event.time NOT BETWEEN segment.start_time AND segment.end_time 
        AND segment.type ("veto1", "veto2")) 
) 
+1

두 번째'EXISTS'의 경우,'event_time'이 거부의 * ANY * 밖에있을 경우 TRUE를 리턴합니다. 따라서 veto1과 충돌하더라도 여전히 veto2 외부에 있으므로 전반적인 조건은 사실이지만 거짓이되기를 원합니다. 이 링크를 참조하십시오 ... http://sqlfiddle.com/#!5/f6957/1 * (내 이벤트는 2 이벤트 만 반환하고, 이벤트 1 및 이벤트 2는 이벤트로 반환됩니다) * – MatBailie