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

Kueri untuk menghitung nilai yang berbeda dalam rentang tanggal bergulir

Kasus uji:

CREATE TABLE tbl (date date, email text);
INSERT INTO tbl VALUES
  ('2012-01-01', '[email protected]')
, ('2012-01-01', '[email protected]')
, ('2012-01-01', '[email protected]')
, ('2012-01-02', '[email protected]')
, ('2012-01-02', '[email protected]')
, ('2012-01-03', '[email protected]')
, ('2012-01-04', '[email protected]')
, ('2012-01-05', '[email protected]')
, ('2012-01-05', '[email protected]')
, ('2012-01-06', '[email protected]')
, ('2012-01-06', '[email protected]')
, ('2012-01-06', '[email protected]`')
;

Kueri - hanya mengembalikan hari di mana ada entri di tbl :

SELECT date
     ,(SELECT count(DISTINCT email)
       FROM   tbl
       WHERE  date BETWEEN t.date - 2 AND t.date -- period of 3 days
      ) AS dist_emails
FROM   tbl t
WHERE  date BETWEEN '2012-01-01' AND '2012-01-06'  
GROUP  BY 1
ORDER  BY 1;

Atau - kembalikan sepanjang hari dalam rentang yang ditentukan, meskipun tidak ada baris untuk hari itu:

SELECT date
     ,(SELECT count(DISTINCT email)
       FROM   tbl
       WHERE  date BETWEEN g.date - 2 AND g.date
      ) AS dist_emails
FROM  (SELECT generate_series(timestamp '2012-01-01'
                            , timestamp '2012-01-06'
                            , interval  '1 day')::date) AS g(date);

db<>main biola di sini

Hasil:

day        | dist_emails
-----------+------------
2012-01-01 | 3
2012-01-02 | 3
2012-01-03 | 3
2012-01-04 | 3
2012-01-05 | 1
2012-01-06 | 2

Ini terdengar seperti pekerjaan untuk fungsi jendela pada awalnya, tetapi saya tidak menemukan cara untuk menentukan bingkai jendela yang sesuai. Juga, per dokumentasi:

Fungsi jendela agregat, tidak seperti fungsi agregat normal, tidak mengizinkan DISTINCT atau ORDER BY untuk digunakan dalam daftar argumen fungsi.

Jadi saya menyelesaikannya dengan subqueries yang berkorelasi sebagai gantinya. Saya rasa itu cara paling cerdas.

BTW, "antara tanggal tersebut dan 3 hari yang lalu" akan menjadi periode 4 hari. Definisi Anda kontradiktif di sana.

Sedikit lebih pendek, tetapi lebih lambat selama beberapa hari:

SELECT g.date, count(DISTINCT email) AS dist_emails
FROM  (SELECT generate_series(timestamp '2012-01-01'
                            , timestamp '2012-01-06'
                            , interval  '1 day')::date) AS g(date)
LEFT   JOIN tbl t ON t.date BETWEEN g.date - 2 AND g.date
GROUP  BY 1
ORDER  BY 1;

Terkait:

  • Membuat deret waktu antara dua tanggal di PostgreSQL
  • Jumlah baris yang bergulir dalam interval waktu


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Kesalahan:pg_config executable tidak ditemukan saat menginstal psycopg2 di Alpine di Docker

  2. Bagaimana cara menginstal hanya alat klien untuk PostgreSQL di Windows?

  3. Menggunakan JSONB di PostgreSQL:Cara Efektif Menyimpan &Mengindeks Data JSON di PostgreSQL

  4. Cara Menyebarkan Teamcity dengan PostgreSQL untuk Ketersediaan Tinggi

  5. Cara Mengonfigurasi Replikasi Cluster-to-Cluster untuk PostgreSQL