PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Masalah 'Kesenjangan dan Pulau' yang rumit

Tidak jelas bagaimana Anda menentukan type untuk setiap periode. Saya memilih jumlah minimum.

Dengan asumsi definisi tabel dasar ini:

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

Pada dasarnya, saya menyarankan fungsi jendela dalam dua subquery bersarang untuk mengidentifikasi anggota dari periode yang sama (pulau). Kemudian agregat:

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;

Hasil (berdasarkan data contoh Anda):

  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

Jika hari yang sama untuk orang yang sama dapat dimasukkan beberapa kali dengan jenis yang berbeda, dan Anda hanya ingin menghitung berbeda hari, buatlah:count(DISTINCT eventdate) AS days .

Terkait, dengan penjelasan rinci:

BTW, eventdate - 6 bekerja untuk tipe data date , tetapi tidak untuk 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. Praktik Terbaik Pencatatan Audit PostgreSQL

  2. Rails + Postgres drop error:database sedang diakses oleh pengguna lain

  3. Deteksi dan hapus celah dalam deret waktu

  4. Setel ulang pg_stat_statements dengan Google Cloud SQL

  5. Driver postgresql JDBC tidak ditemukan di proyek Android