Tổng khoảng thời gian của các ngày trong cùng một cột


10

Làm thế nào để bạn tổng hợp tốt nhất sự khác biệt của một phạm vi ngày trong cùng một cột giữa các hàng xen kẽ? Tôi có một cột Ngày tháng và muốn tính toán sự khác biệt giữa các hàng. Tôi muốn sự khác biệt trong Giây. Câu hỏi này không phải là làm thế nào để có sự khác biệt giữa 2 dấu thời gian, mà tập trung nhiều hơn vào cách tính toán hiệu quả nhất giữa các hàng trên cùng một bảng. Trong trường hợp của tôi, mỗi hàng có một kiểu sự kiện datetime liên kết 2 hàng với nhau một cách hợp lý.

Chi tiết liên quan đến cách nhóm các sự kiện bắt đầu và kết thúc. (Câu hỏi của Andriy M) Bắt đầu và kết thúc "nên" liên tiếp. Nếu một Bắt đầu không có kết thúc tiếp theo thì nó nên được bỏ ra khỏi tổng. Di chuyển đến Bắt đầu tiếp theo để xem nếu nó kết thúc. Chỉ nên thêm các cặp Bắt đầu - Kết thúc liên tiếp vào tổng của tổng số giây.

Làm việc trong postgresql 9.x ...

Dữ liệu ví dụ trong bảng;

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

Lưu ý, Tất cả các Ngày bắt đầu và Ngày kết thúc sẽ tuần tự.

Đây là nỗ lực đầu tiên của tôi. Có vẻ như đang làm việc.

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 

Nỗ lực đầu tiên của tôi dựa trên một ví dụ tuyệt vời từ stackoverflow Postgres 9.1 - Nhận giá trị tiếp theo

Ghi chú; Bạn có thể nhận xét NHÓM THEO và SUM và hủy nhận xét bắt đầu. * Để nhận bản ghi cho từng khoảng thời gian riêng lẻ đi vào tổng.

Câu trả lời:


10

Bạn có thể sử dụng LEADchức năng phân tích để lấy dữ liệu của hàng tiếp theo eventtypeeventdatedọc theo dữ liệu của hàng hiện tại:

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'

Sử dụng truy vấn trên dưới dạng bảng dẫn xuất, bạn có thể lọc đầu ra hơn nữa eventtype = 'START' AND nexttype = 'END'và nhận tổng số chênh lệch:

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'
;

Là một biến thể nhỏ, bạn có thể triển khai truy vấn con dưới dạng 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'
;

Việc viết lại này có thể có ý nghĩa đối với hiệu năng, vì không giống như bảng dẫn xuất, CTE được cụ thể hóa trong PostgreQuery. Kiểm tra sẽ tiết lộ nếu có sự khác biệt và, nếu vậy, tùy chọn nào tốt hơn cho bạn.


Thưa ngài, cảm ơn! Tôi sẽ thử phiên bản CTE và xem nó giúp như thế nào.
C Smith
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.