यह स्पष्ट नहीं है कि आप type
का निर्धारण कैसे करते हैं प्रत्येक अवधि के लिए। मैंने न्यूनतम संख्या चुनी है।
इस मूल तालिका परिभाषा को मानते हुए:
CREATE TABLE tbl (person text, eventdate date, type int);
मूल रूप से, मेरा सुझाव है कि विंडो फ़ंक्शंस समान अवधि (द्वीप) के सदस्यों की पहचान करने के लिए दो नेस्टेड उपश्रेणियों में। फिर एकत्र करें:
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;
परिणाम (आपके उदाहरण डेटा के आधार पर):
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
यदि एक ही व्यक्ति के लिए एक ही दिन को विभिन्न प्रकार के साथ कई बार दर्ज किया जा सकता है, और आप केवल विशिष्ट की गणना करना चाहते हैं दिन, इसे बनाएं:count(DISTINCT eventdate) AS days
।
संबंधित, विस्तृत विवरण के साथ:
- सबसे लंबे क्रम को चुनें
- पोस्टग्रेस्क्ल में समूहों को कैसे लेबल करें जब संबंधित समूह पिछली पंक्ति पर निर्भर करता है?
बीटीडब्ल्यू, eventdate - 6
डेटा प्रकार के लिए काम करता है date
, लेकिन timestamp
. के लिए नहीं :