sql >> Databasteknik >  >> RDS >> PostgreSQL

Komplex "Gaps and Islands"-fråga

Det är oklart hur du bestämmer type för varje period. Jag valde det lägsta antalet.

Förutsatt att denna grundläggande tabelldefinition:

CREATE TABLE tbl (person text, eventdate date, type int);

I grund och botten föreslår jag fönsterfunktioner i två kapslade underfrågor för att identifiera medlemmar från samma period (ö). Aggregera sedan:

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;

Resultat (baserat på dina exempeldata):

  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

Om samma dag för samma person kan anges flera gånger med olika typer, och du bara vill räkna distinkt dagar, gör det:count(DISTINCT eventdate) AS days .

Relaterat, med detaljerad förklaring:

BTW, eventdate - 6 fungerar för datatypen date , men inte för timestamp :




  1. Hämtar ofullständigt objekt med Hibernate Mapping som inbyggd fråga

  2. Försöker installera innodb memcached plugin MySQL5.6.17 på ubuntu 14.04

  3. Det går inte att ansluta till SQL Server med PHP

  4. Lagring av hexadecimala värden som binär i MySQL