복붙노트

[SQL] SQL에서 한 번에 간격을 병합

SQL

SQL에서 한 번에 간격을 병합

하자 내가 두 개의 열이있는 테이블이 있다고 가정 : 시작과 끝, 두 정수를, 테이블은 첫 번째, 그 다음 두 번째 열을 기준으로 정렬됩니다. 각 행 간격을 나타낸다.

내가 필요한 것은 병합 간격의 테이블 : 모든 중복 또는 인접한 간격 하나에 탐욕스럽게 먹게.

그것은이 쿼리 가입으로 구성,하지만 내 경우에는 400 만 개 행이 행의 수에 차있다 할 수있다 (I 쿼리가 여전히 실행되고 있기 때문에이 질문을 구성하기로 결정했다).

표준 SQL에서,하지만 어떻게 그것을 수행하는 방법 또는 이에 해당하는 - 또한 각 행을 실행하고 최대 종료 시간을 추적함으로써, 단일 패스에서 할 수 있는가? SQL에서 그것을 할 수 있습니다 어떤 O (n)의 방법인가? 지금은 SQLite는을 사용하고 있습니다; SQLite는 특정 솔루션은이 시간을 나를 도움이 될 것이다.

관련 질문 (1, 2, 3, 4, 5, 6, 7, 8, 9)에 대한 답변에서 나는 그것이 가능 여부를 알 수 없습니다.

너는 할수 있니?

해결법

  1. ==============================

    1.음, 여기 MySQL을 작동하는 솔루션은 (는 SQLite는에 작동하는지 모르겠어요)입니다. 내가 생각하지만 증명할 수, 즉, O (N)이다 (그것은 이미 내가 질문 상태를 생각으로 분류 된 경우, 처음에, 즉 사건의 테이블을 정렬하는 데 걸리는 시간을 폐기은.)

    음, 여기 MySQL을 작동하는 솔루션은 (는 SQLite는에 작동하는지 모르겠어요)입니다. 내가 생각하지만 증명할 수, 즉, O (N)이다 (그것은 이미 내가 질문 상태를 생각으로 분류 된 경우, 처음에, 즉 사건의 테이블을 정렬하는 데 걸리는 시간을 폐기은.)

    > SELECT * from events;
    +-------+-----+
    | start | end |
    +-------+-----+
    |     1 |   9 |
    |     5 |   8 |
    |     8 |  11 |
    |    11 |  13 |
    |    17 |  25 |
    |    18 |  26 |
    |    33 |  42 |
    |    59 |  81 |
    |    61 |  87 |
    |    97 | 132 |
    |   105 | 191 |
    |   107 | 240 |
    |   198 | 213 |
    |   202 | 215 |
    +-------+-----+
    14 rows in set (0.00 sec)
    
    
    SET @interval_id = 0;
    SET @interval_end = 0;
    
    SELECT
      MIN(start) AS start,
      MAX(end) AS end
      FROM
        (SELECT
           @interval_id := IF(start > @interval_end,
                              @interval_id + 1,
                              @interval_id) AS interval_id,
           @interval_end := IF(start < @interval_end,
                               GREATEST(@interval_end, end),
                               end) AS interval_end,
           events.*
         FROM events
         ORDER BY start,end) tmp
      GROUP BY interval_id;
    
    +-------+------+
    | start | end  |
    +-------+------+
    |     1 |   13 |
    |    17 |   26 |
    |    33 |   42 |
    |    59 |   87 |
    |    97 |  240 |
    +-------+------+
    5 rows in set (0.00 sec)
    
  2. ==============================

    2.귀하의 링크에서 하나를 생략 한 : 수 있습니까 날짜를 교차 병합하기 위해 SQL 서버 CTE를 사용할 수 있습니까? 여기서 I는 중첩 간격 문제 재귀 CTE 솔루션을 제시한다. 재귀 CTE의는 종종 놀라 울 정도로 빠르게 수행 (보통 자기 조인에 비해) 다르게 처리 할 수 ​​있습니다.

    귀하의 링크에서 하나를 생략 한 : 수 있습니까 날짜를 교차 병합하기 위해 SQL 서버 CTE를 사용할 수 있습니까? 여기서 I는 중첩 간격 문제 재귀 CTE 솔루션을 제시한다. 재귀 CTE의는 종종 놀라 울 정도로 빠르게 수행 (보통 자기 조인에 비해) 다르게 처리 할 수 ​​있습니다.

    MySQL은 재귀 CTE는 없습니다. 포스트 그레스는 마이크로 소프트를 가지고, 오라클을 가지고, 그들을있다.

    여기에 포스트 그레스의 연속 컬럼의 '실행'에 대한 쿼리 것은 퍼지 요인과 또 다른 하나입니다.

    파손되지 순서는 또 다른 하나의 경우 여기에 여러 행에서 총 시간 간격을 가져옵니다.

  3. ==============================

    3.코멘트에 내 질문에 대한 답을 바탕으로, 내 생각 일 것입니다 생각하지 않습니다. 당신이 할 수있는 당신을 언급 한 (그리고 난 당신이 방법을 알고 가정)이 조인와 함께 할 수 있기 때문에, 나는 유지에 합류 할 행의 수를 최소화하는 생각을했다 단지의 범위가 다음과 같은 별개의 사항에 속한다 :

    코멘트에 내 질문에 대한 답을 바탕으로, 내 생각 일 것입니다 생각하지 않습니다. 당신이 할 수있는 당신을 언급 한 (그리고 난 당신이 방법을 알고 가정)이 조인와 함께 할 수 있기 때문에, 나는 유지에 합류 할 행의 수를 최소화하는 생각을했다 단지의 범위가 다음과 같은 별개의 사항에 속한다 :

    select start, max(end) as end
    from (
          select min(start) as start,end
          from table
          group by end
         ) in_tab
    group by in_tab.start
    

    위의 내부를 선택 차종 확인하십시오 끝이 포인트 반복 및 선택 각 끝의 긴 시작점. 외부 선택은 그 반대입니다. 우리는 (삭제 된 FULLY 함유 / 중첩 범위) 다른 지점에서 시작 및 종료 범위로 끝낸다. 최대 범위가 큰 아니었다면이 일을했을 수도 있습니다. 이 날짜했다 거기에, 다음은 365 * 364 옵션은 두 점을 선택하는이었을 것이다 그것에 경우 최고 연도 전체 테이블 낮은 날짜의 차이와 가장 최신이며, 그것이 가능한 행에 대한 높은 제한했을 경우 위의 선택 후. 다음은 다음은 당신이 이미 가지고 방법을 결합하여 임시 테이블에 사용 된 수 있습니다. 하지만 당신이 언급 한 숫자, 다음 이론적으로 우리는이 시도는 무관하게 엄청난 수 있습니다. 심지어 행이 계산에 사용되는 위의 최소화하지만, 그들은 여전히 ​​너무 많은 조인에서 사용하는 것입니다.

    나는 RDBMS에서 제공하는 다른 비 표준 기능이없는 경우에 가입하지 않고 ANSI SQL이를 만들 수있는 방법을 알고하지 않습니다. 오라클, 예를 들어이 쉽게 분석 기능을 달성 할 수있다. 최적의 사용 행의 수를 최소화하고 응용 프로그램에 그들을 데리고 위를 사용하는 것이이 경우에있을 것입니다 그리고 당신은 계산 범위와 다시 데이터베이스에 삽입하는 것이 코드를이 작성할 수 있습니다.

  4. ==============================

    4.지금은, 내가 찾은 최고의 대답은 : 사용 색인. 이것은 (N N 로그) O에 차에서 복잡성 다운을 제공합니다.

    지금은, 내가 찾은 최고의 대답은 : 사용 색인. 이것은 (N N 로그) O에 차에서 복잡성 다운을 제공합니다.

    코팅이 인덱스, 쿼리 내 요구에 충분히 빨리 밝혀졌다; 시작 또는 끝 열 중 하나에 불과 인덱스로, 그것은 확인을 여전히 느리지 만했다. 각각의 경우에, 쿼리 계획은 예상대로 단일 테이블 스캔, 인덱스의 사용과 결합되는 것을 저에게 말했다 설명한다.

    인덱스의 요소를 찾는 것은 매우 O (1)이 아니라 충분히 가까이로 밝혀졌다. 그리고 인덱스를 구축하거나, 느린 없습니다.

    어떤 남아있는 것은 사실 O (n)이 알고리즘은 SQL로 작성 될 수 없다는 증거입니다.

    그래서 다른 대답은 다른 언어로 그것을 작성하고 다음 SQLite는 테이블에 적용하는 것입니다. 그 일을하는 데는 여러 가지 방법이있을 수 있습니다 :

  5. from https://stackoverflow.com/questions/8451925/merging-intervals-in-one-pass-in-sql by cc-by-sa and MIT license