PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Комплексен проблем с „пропуски и острови“.

Не е ясно как определяте 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 :




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Как да създавате и изтривате бази данни и таблици в PostgreSQL

  2. Комбинирайте няколко израза SELECT

  3. модулно тестване с база данни в паметта

  4. Postgres избира всички колони, но групира по една колона

  5. rails - postgres грешка:Причина:Несъвместима версия на библиотеката:libpq.5.dylib изисква версия 1.0.0 или по-нова,