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

Chọn nhóm người dùng riêng biệt theo phạm vi thời gian

Đếm tất cả hàng

SELECT date, '1_D' AS time_series,  count(DISTINCT user_id) AS cnt
FROM   uniques
GROUP  BY 1

UNION  ALL
SELECT DISTINCT ON (1)
       date, '2_W', count(*) OVER (PARTITION BY week_beg ORDER BY date)
FROM   uniques

UNION  ALL
SELECT DISTINCT ON (1)
       date, '3_M', count(*) OVER (PARTITION BY month_beg ORDER BY date)
FROM   uniques
ORDER  BY 1, time_series
  • Các cột của bạn week_begmonth_beg 100% dư thừa và có thể dễ dàng thay thế bằng date_trunc('week', date + 1) - 1date_trunc('month', date) tương ứng.

  • Tuần của bạn dường như bắt đầu vào Chủ nhật (giảm từng người một), do đó + 1 .. - 1 .

  • khung mặc định của hàm cửa sổ với ORDER BY trong OVER mệnh đề sử dụng là RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW . Đó chính xác là những gì bạn cần.

  • Sử dụng UNION ALL , không phải UNION .

  • Sự lựa chọn đáng tiếc của bạn cho time_series (D, W, M) không được sắp xếp tốt, tôi đã đổi tên để tạo ORDER BY cuối cùng dễ dàng hơn.

  • Truy vấn này có thể xử lý nhiều hàng mỗi ngày. Số lượng bao gồm tất cả các đồng nghiệp trong một ngày.

  • Tìm hiểu thêm về DISTINCT ON :

DISTINCT người dùng mỗi ngày

Để đếm mọi người dùng chỉ một lần mỗi ngày, hãy sử dụng CTE với DISTINCT ON :

WITH x AS (SELECT DISTINCT ON (1,2) date, user_id FROM uniques)
SELECT date, '1_D' AS time_series,  count(user_id) AS cnt
FROM   x
GROUP  BY 1

UNION ALL
SELECT DISTINCT ON (1)
       date, '2_W'
      ,count(*) OVER (PARTITION BY (date_trunc('week', date + 1)::date - 1)
                      ORDER BY date)
FROM   x

UNION ALL
SELECT DISTINCT ON (1)
       date, '3_M'
      ,count(*) OVER (PARTITION BY date_trunc('month', date) ORDER BY date)
FROM   x
ORDER BY 1, 2

DISTINCT người dùng trong khoảng thời gian động

Bạn luôn có thể sử dụng truy vấn phụ tương quan . Có xu hướng chậm với các bảng lớn!
Xây dựng dựa trên các truy vấn trước đó:

WITH du AS (SELECT date, user_id FROM uniques GROUP BY 1,2)
    ,d  AS (
    SELECT date
          ,(date_trunc('week', date + 1)::date - 1) AS week_beg
          ,date_trunc('month', date)::date AS month_beg
    FROM   uniques
    GROUP  BY 1
    )
SELECT date, '1_D' AS time_series,  count(user_id) AS cnt
FROM   du
GROUP  BY 1

UNION ALL
SELECT date, '2_W', (SELECT count(DISTINCT user_id) FROM du
                     WHERE  du.date BETWEEN d.week_beg AND d.date )
FROM   d
GROUP  BY date, week_beg

UNION ALL
SELECT date, '3_M', (SELECT count(DISTINCT user_id) FROM du
                     WHERE  du.date BETWEEN d.month_beg AND d.date)
FROM   d
GROUP  BY date, month_beg
ORDER  BY 1,2;

SQL Fiddle cho cả ba giải pháp.

Nhanh hơn với dense_rank()

@Clodoaldo đã đưa ra một cải tiến lớn:sử dụng chức năng cửa sổ dense_rank() . Đây là một ý tưởng khác cho một phiên bản được tối ưu hóa. Việc loại trừ các bản sao hàng ngày ngay lập tức sẽ nhanh hơn. Hiệu suất tăng theo số hàng mỗi ngày.

Xây dựng dựa trên mô hình dữ liệu được đơn giản hóa và hoàn thiện - không có cột thừa- day dưới dạng tên cột thay vì day

day là một từ dành riêng trong SQL chuẩn và tên kiểu cơ bản trong PostgreSQL và không nên được sử dụng làm định danh.

CREATE TABLE uniques(
   day date     -- instead of "date"
  ,user_id int
);

Truy vấn được cải thiện:

WITH du AS (
   SELECT DISTINCT ON (1, 2)
          day, user_id 
         ,date_trunc('week',  day + 1)::date - 1 AS week_beg
         ,date_trunc('month', day)::date         AS month_beg
   FROM   uniques
   )
SELECT day, count(user_id) AS d, max(w) AS w, max(m) AS m
FROM  (
    SELECT user_id, day
          ,dense_rank() OVER(PARTITION BY week_beg  ORDER BY user_id) AS w
          ,dense_rank() OVER(PARTITION BY month_beg ORDER BY user_id) AS m
    FROM   du
    ) s
GROUP  BY day
ORDER  BY day;

SQL Fiddle thể hiện hiệu suất của 4 biến thể nhanh hơn. Điều này phụ thuộc vào việc phân phối dữ liệu của bạn để nhanh nhất cho bạn.
Tất cả chúng đều nhanh hơn khoảng 10 lần so với phiên bản truy vấn con tương quan (điều này không tệ đối với các truy vấn con tương quan).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Chuyển từ MSSQL sang PostgreSQL - Điều bạn nên biết

  2. Làm thế nào để đọc JSON từ Cơ sở dữ liệu Doobie Scala PostgreSQL với Circe?

  3. Tổng quan về Lập trình phía máy chủ trong PostgreSQL

  4. người dùng được đánh dấu bằng nhãn theo thời gian cho mỗi tháng

  5. PostgreSQL:Xóa thuộc tính khỏi cột JSON