같은 열에있는 날짜의 합계 간격


10

인터리빙 행 사이의 동일한 열에서 날짜 범위의 차이점을 가장 잘 요약하는 방법은 무엇입니까? Datetime 열이 있고 행의 차이를 계산하려고합니다. 초의 차이를 원합니다. 이 질문은 두 타임 스탬프 간의 차이를 얻는 방법에 대한 것이 아니라 같은 테이블의 행 간을 가장 효율적으로 계산하는 방법에 중점을 둡니다. 필자의 경우 각 행에는 2 개의 행을 논리적으로 연결하는 datetime eventype이 있습니다.

세부 사항 시작 및 종료의 이벤트 유형을 그룹화하는 방법과 관련이 있습니다. (앤드리 M의 질문) 시작과 끝은 "연속해야한다". 시작에 후속 종료가 없으면 합계에서 제외되어야합니다. 다음 시작으로 이동하여 끝이 있는지 확인하십시오. 총 초 합계에 연속적인 시작-끝 쌍만 추가해야합니다.

postgresql 9.x에서 작업 중 ...

테이블의 예제 데이터;

eventtype, eventdate
START, 2015-01-01 14:00
END, 2015-01-01 14:25
START, 2015-01-01 14:30
END, 2015-01-01 14:43
START, 2015-01-01 14:45
END, 2015-01-01 14:49
START, 2015-01-01 14:52
END, 2015-01-01 14:55

모든 시작 날짜와 종료 날짜는 순차적입니다.

여기 내 첫 시도가 있습니다. 작동하는 것 같습니다.

SELECT 
-- starts.*
SUM(EXTRACT(EPOCH FROM (eventdate_next - eventdate))) AS duration_seconds
FROM
( 
    WITH x AS (
        SELECT *, dense_rank() OVER (ORDER BY eventdate) AS rnk
        FROM   table
        AND eventdate > '2015-01-01 00:00:00.00'
        AND eventdate < '2016-01-01 23:59:59.59' 
        )
    SELECT x.eventdate, x.eventtype, y.eventdate AS eventdate_next,  y.eventtype AS eventtype_next
    FROM   x
    LEFT   JOIN (SELECT DISTINCT eventdate, eventtype, rnk FROM x) y ON y.rnk = (x.rnk + 1)
    ORDER  BY x.eventdate
) starts
WHERE
eventtype = 'START'   
GROUP BY eventtype 

내 첫 번째 시도는 stackoverflow Postgres 9.1-다음 값 얻기의 훌륭한 예를 기반으로 합니다.

노트; GROUP BY 및 SUM에 주석을 달고 시작을 주석 해제하십시오. * 각 지속 시간에 대한 레코드를 합산으로 가져옵니다.

답변:


10

LEAD분석 함수를 사용하여 다음 행 eventtypeeventdate현재 행의 데이터 를 얻을 수 있습니다 .

SELECT
  eventtype,
  eventdate,
  LEAD(eventtype) OVER (ORDER BY eventdate) AS nexttype,
  LEAD(eventdate) OVER (ORDER BY eventdate) AS nextdate
FROM
  atable
WHERE
      eventdate >= '2015-01-01 00:00:00.00'
  AND eventdate <  '2016-01-01 23:59:59.59'

위의 쿼리를 파생 테이블로 사용하여 결과를 더 필터링 eventtype = 'START' AND nexttype = 'END'하고 차이의 합계를 얻을 수 있습니다.

SELECT
  SUM(EXTRACT(EPOCH FROM (nextdate - eventdate))) AS duration_seconds
FROM
  (
    SELECT
      eventtype,
      eventdate,
      LEAD(eventtype) OVER (ORDER BY eventdate) AS nexttype,
      LEAD(eventdate) OVER (ORDER BY eventdate) AS nextdate
    FROM
      atable
    WHERE
          eventdate >= '2015-01-01 00:00:00.00'
      AND eventdate <  '2016-01-01 23:59:59.59'
  ) AS s
WHERE
      eventtype = 'START'
  AND nexttype  = 'END'
;

약간의 변형으로 하위 쿼리를 CTE로 구현할 수 있습니다.

WITH cte AS
  (
    SELECT
      eventtype,
      eventdate,
      LEAD(eventtype) OVER (ORDER BY eventdate) AS nexttype,
      LEAD(eventdate) OVER (ORDER BY eventdate) AS nextdate
    FROM
      atable
    WHERE
          eventdate >= '2015-01-01 00:00:00.00'
      AND eventdate <  '2016-01-01 23:59:59.59'
  )
SELECT
  SUM(EXTRACT(EPOCH FROM (nextdate - eventdate))) AS duration_seconds
FROM
  cte
WHERE
      eventtype = 'START'
  AND nexttype  = 'END'
;

파생 테이블과 달리 CTE는 PostgreSQL에서 구체화되기 때문에이 재 작성은 성능에 영향을 줄 수 있습니다. 테스트를 통해 차이가 있는지 확인하고 필요한 경우 어떤 옵션이 더 적합한 지 확인해야합니다.


앤디, 고마워! 나는 CTE 버전을 시도하고 그것이 어떻게 도움이되는지 볼 것이다.
C Smith
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.