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:
- Thời gian tạo chuỗi giữa hai ngày trong PostgreSQL
- Tham gia truy vấn đếm trên create_series trong postgres và cũng truy xuất giá trị Null là" 0 "
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: