Es ist unklar, wie Sie den type
bestimmen für jede Periode. Ich habe die Mindestanzahl gewählt.
Angenommen diese grundlegende Tabellendefinition:
CREATE TABLE tbl (person text, eventdate date, type int);
Grundsätzlich empfehle ich Fensterfunktionen in zwei verschachtelten Unterabfragen, um Mitglieder derselben Periode (Insel) zu identifizieren. Dann aggregieren:
SELECT person, period
, min(eventdate) AS startdate
, max(eventdate) AS enddate
, count(*) AS days
, min(type) AS type
FROM (
SELECT person, eventdate, type
, count(gap) OVER (PARTITION BY person ORDER BY eventdate) AS period
FROM (
SELECT person, eventdate, type
, CASE WHEN lag(eventdate) OVER (PARTITION BY person ORDER BY eventdate)
> eventdate - 6 -- within 5 days
THEN NULL -- same period
ELSE TRUE -- next period
END AS gap
FROM tbl
) sub
) sub
GROUP BY person, period
ORDER BY person, period;
Ergebnis (basierend auf Ihren Beispieldaten):
person | period | startdate | enddate | days | type
----------+--------+------------+------------+------+------
<uuid-1> | 1 | 2016-05-14 | 2016-05-22 | 5 | 300
<uuid-1> | 2 | 2016-05-30 | 2016-06-01 | 2 | 300
<uuid-1> | 3 | 2016-06-21 | 2016-06-21 | 1 | 300
<uuid-2> | 1 | 2016-05-22 | 2016-05-27 | 2 | 301
<uuid-2> | 2 | 2016-06-15 | 2016-06-23 | 4 | 300
<uuid-2> | 3 | 2016-06-30 | 2016-06-30 | 1 | 300
<uuid-3> | 1 | 2016-05-14 | 2016-05-14 | 1 | 300
<uuid-3> | 2 | 2016-06-30 | 2016-06-30 | 1 | 300
<uuid-4> | 1 | 2016-06-16 | 2016-06-16 | 1 | 300
<uuid-4> | 2 | 2016-06-30 | 2016-06-30 | 1 | 300
<uuid-5> | 1 | 2016-06-20 | 2016-06-20 | 1 | 300
Wenn derselbe Tag für dieselbe Person mehrfach mit unterschiedlichen Typen erfasst werden kann und Sie nur eindeutig zählen möchten Tage, mache daraus:count(DISTINCT eventdate) AS days
.
Verwandte, mit ausführlicher Erklärung:
- Längste fortlaufende Sequenz auswählen
- Wie werden Gruppen in Postgresql gekennzeichnet, wenn die Gruppenzugehörigkeit von der vorangehenden Zeile abhängt?
Übrigens, eventdate - 6
funktioniert für den Datentyp date
, aber nicht für timestamp
: