PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Truy vấn số lượng các giá trị riêng biệt trong một phạm vi ngày luân phiên

Trường hợp thử nghiệm:

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]`')
;

Truy vấn - chỉ trả về những ngày có mục nhập trong 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;

Hoặc - trở lại tất cả các ngày trong phạm vi được chỉ định, ngay cả khi không có hàng nào trong ngày:

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 <> fiddle here

Kết quả:

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

Điều này nghe có vẻ giống như một công việc cho các chức năng cửa sổ lúc đầu, nhưng tôi không tìm ra cách xác định khung cửa sổ phù hợp. Ngoài ra, theo tài liệu:

Các hàm cửa sổ tổng hợp, không giống như các hàm tổng hợp bình thường, không cho phép DISTINCT hoặc ORDER BY được sử dụng trong danh sách đối số hàm.

Vì vậy, tôi đã giải quyết nó bằng các truy vấn con tương quan. Tôi đoán đó là cách thông minh nhất.

BTW, "từ ngày đã nói đến 3 ngày trước" sẽ là khoảng thời gian 4 ngày. Định nghĩa của bạn mâu thuẫn ở đó.

Ngắn hơn một chút, nhưng chậm hơn trong vài ngày:

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;

Có liên quan:

  • Tạo chuỗi thời gian giữa hai ngày trong PostgreSQL
  • Số lần cuộn của các hàng trong khoảng thời gian hoạt động


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tích hợp PostgreSQL với hệ thống xác thực

  2. Cách đặt thời gian chờ kết nối trong SQLAlchemy

  3. Tính đa hình trong bảng cơ sở dữ liệu SQL?

  4. Rails:Quyền Postgres bị từ chối tạo cơ sở dữ liệu trên rake db:create:all

  5. Postgres kích hoạt sau khi chèn truy cập MỚI