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

Nhận ứng dụng có số lượt đánh giá cao nhất kể từ một chuỗi ngày năng động

Tôi nghĩ rằng đây là những gì bạn đang tìm kiếm:

Postgres 13 hoặc mới hơn

WITH cte AS (  -- MATERIALIZED
   SELECT app_id, min(review_date) AS earliest_review, count(*)::int AS total_ct
   FROM   reviews
   GROUP  BY 1
   )
SELECT *
FROM  (
   SELECT generate_series(min(review_date)
                        , max(review_date)
                        , '1 day')::date
   FROM   reviews
   ) d(review_window_start)
LEFT  JOIN LATERAL (
   SELECT total_ct, array_agg(app_id) AS apps
   FROM  (
      SELECT app_id, total_ct
      FROM   cte c
      WHERE  c.earliest_review >= d.review_window_start
      ORDER  BY total_ct DESC
      FETCH  FIRST 1 ROWS WITH TIES  -- new & hot
      ) sub
   GROUP  BY 1
   ) a ON true;

WITH TIES làm cho nó rẻ hơn một chút. Đã thêm vào Postgres 13 (hiện đang là phiên bản beta). Xem:

Postgres 12 tuổi trở lên

WITH cte AS (  -- MATERIALIZED
   SELECT app_id, min(review_date) AS earliest_review, count(*)::int AS total_ct
   FROM   reviews
   GROUP  BY 1
   )
SELECT *
FROM  (
   SELECT generate_series(min(review_date)
                        , max(review_date)
                        , '1 day')::date
   FROM   reviews
   ) d(review_window_start)
LEFT  JOIN LATERAL (
   SELECT total_ct, array_agg(app_id) AS apps
   FROM  (
      SELECT total_ct, app_id
          ,  rank() OVER (ORDER BY total_ct DESC) AS rnk
      FROM   cte c
      WHERE  c.earliest_review >= d.review_window_start
      ) sub
   WHERE  rnk = 1
   GROUP  BY 1
   ) a ON true;

db <> fiddle tại đây

Tương tự như trên, nhưng không có WITH TIES .

Chúng ta không cần liên quan đến apps trong bảng ở tất cả. Bảng reviews có tất cả thông tin chúng tôi cần.

CTE cte tính toán đánh giá sớm nhất và tổng số hiện tại cho mỗi ứng dụng. CTE tránh tính toán lặp lại. Sẽ hữu ích một chút.
Nó luôn được hiện thực hóa trước Postgres 12 và sẽ được hiện thực hóa tự động trong Postgres 12 vì nó được sử dụng nhiều lần trong truy vấn chính. Nếu không, bạn có thể thêm từ khóa MATERIALIZED trong Postgres 12 trở lên để buộc nó. Xem:

generate_series() được tối ưu hóa cuộc gọi sản xuất chuỗi ngày từ đánh giá sớm nhất đến mới nhất. Xem:

Cuối cùng, LEFT JOIN LATERAL bạn đã được khám phá. Nhưng vì nhiều ứng dụng có thể ràng buộc để có nhiều bài đánh giá nhất, hãy truy xuất tất cả những người chiến thắng, có thể là 0 - n ứng dụng. Truy vấn tổng hợp tất cả những người chiến thắng hàng ngày vào một mảng, vì vậy chúng tôi nhận được một hàng kết quả duy nhất cho mỗi review_window_start . Ngoài ra, hãy xác định (các) tiebreaker để nhận được nhiều nhất một người chiến thắng. Xem:



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Trình diễn SQL injection trong PL / pgSQL

  2. postgres truy vấn động

  3. Hoạt động CASCADE có điều kiện cho ràng buộc khóa ngoại?

  4. Autoincrement trong liquibase

  5. 7 mẹo thực hành tốt nhất để tải dữ liệu hàng loạt PostgreSQL