Aynı sütundaki Toplam Tarih Aralığı


10

Serpiştirme satırları arasındaki aynı sütundaki bir tarih aralığının farklılıklarını en iyi nasıl toplarsınız? Bir Datetime sütun var ve satırlar arasındaki farkı hesaplamak istiyorum. Saniyedeki farkı istiyorum. Bu sorular 2 zaman damgası arasında bir farkın nasıl elde edileceği ile ilgili değil, aynı tablodaki satırlar arasında en verimli şekilde nasıl hesaplanacağına daha fazla odaklanmaktadır. Benim durumumda, her satır mantıksal olarak 2 satırı birbirine bağlayan bir datetime eventype vardır.

Ayrıntılar Başlangıç ​​ve bitiş olay türlerinin nasıl gruplandırılacağı ile ilgili. (Andriy M'nin Sorusu) Birbirini izleyen “olmalı” başlıyor ve bitiyor. Bir Başlangıç ​​öğesinin sonraki bir sonu yoksa toplamın dışında bırakılmalıdır. Sonunun olup olmadığını görmek için bir sonraki Başlangıç ​​kısmına geçmek. Toplam saniye toplamına yalnızca ardışık Başlangıç ​​- Bitiş Çiftleri eklenmelidir.

Postgresql 9.x içinde çalışıyor ...

Tablodaki örnek veriler;

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

Not: Tüm Başlangıç ​​ve Bitiş Tarihleri ​​sıralı olacaktır.

İşte ilk denemem. Çalışıyor gibi görünüyor.

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 

İlk denemem stackoverflow Postgres 9.1'den harika bir örneğe dayanıyor - Sonraki değeri elde etme

Not; TOPLA ve TOPLA ile yorum yapabilir ve toplamların yorumunu kaldırabilirsiniz. * Toplama giren her bir süre için bir kayıt almak için.

Yanıtlar:


10

Sen kullanabilirsiniz LEADsonraki satır var elde etmek analitik fonksiyon eventtypeve eventdatecari satırın verilerle birlikte:

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'

Yukarıdaki sorguyu türetilmiş bir tablo olarak kullanarak, çıktıyı daha fazla filtreleyebilir eventtype = 'START' AND nexttype = 'END've toplam farkı elde edebilirsiniz:

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

Küçük bir varyasyon olarak, alt sorguyu CTE olarak uygulayabilirsiniz:

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

Bu yeniden yazma işleminin performans üzerinde etkileri olabilir, çünkü türetilmiş bir tablonun aksine, CTE PostgreSQL'de gerçekleştirilmiştir. Test, bir fark olup olmadığını ve eğer varsa, hangi seçeneğin sizin için daha iyi olduğunu ortaya koymalıdır.


Andriy, teşekkürler! CTE sürümünü deneyeceğim ve nasıl yardımcı olduğunu göreceğim.
C Smith
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.