Myslím toto je to, co hledáte:
Postgres 13 nebo novější
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
dělá to o něco levnější. Přidáno v Postgres 13 (aktuálně beta). Viz:
Postgres 12 nebo starší
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 zde
Stejné jako výše, ale bez WITH TIES
.
Nemusíme zapojovat tabulkové apps
vůbec. Tabulka reviews
má všechny informace, které potřebujeme.
CTE cte
vypočítá nejstarší recenzi a aktuální celkový počet na aplikaci. CTE se vyhýbá opakovaným výpočtům. Mělo by to docela pomoci.
Vždy se zhmotní před Postgres 12 a mělo by se zhmotnit automaticky v Postgresu 12, protože se v hlavním dotazu používá mnohokrát. Jinak můžete přidat klíčové slovo MATERIALIZED
v Postgres 12 nebo novější, aby to vynutilo. Viz:
Optimalizovaný generate_series()
call vytváří řadu dní od nejstarší po nejnovější recenzi. Viz:
- Čas generování série mezi dvěma daty v PostgreSQL
- Připojte se k dotazu na počet na create_series v postgresu a také načtěte hodnoty Null jako "0"
Nakonec LEFT JOIN LATERAL
už jsi objevil. Ale protože více aplikací může souviset pro nejvíce recenzí načtěte všechny vítěze, což může být 0 - n aplikací. Dotaz agreguje všechny denní vítěze do pole, takže dostaneme jeden řádek výsledku na review_window_start
. Případně definujte nerozhodný výsledek, abyste získali maximálně jeden vítěz. Viz: