PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Obtenha aplicativos com a maior contagem de avaliações desde uma série dinâmica de dias


Eu acho é isso que você procura:

Postgres 13 ou mais recente

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 deixa um pouco mais barato. Adicionado no Postgres 13 (atualmente beta). Ver:

Postgres 12 ou mais antigo

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 aqui

Igual ao anterior, mas sem WITH TIES .

Não precisamos envolver a tabela apps de forma alguma. A tabela reviews tem todas as informações que precisamos.

O CTE cte calcula a primeira revisão e a contagem total atual por aplicativo. O CTE evita cálculos repetidos. Deve ajudar bastante.
É sempre materializado antes do Postgres 12, e deve ser materializado automaticamente no Postgres 12, pois é usado muitas vezes na consulta principal. Caso contrário, você pode adicionar a palavra-chave MATERIALIZED no Postgres 12 ou posterior para forçá-lo. Ver:

O generate_series() otimizado chamada produz a série de dias da primeira à última revisão. Ver:

Finalmente, o LEFT JOIN LATERAL você já descobriu. Mas como vários aplicativos podem vincular para o maior número de avaliações, recupere todos os vencedores, que podem ser 0 - n apps. A consulta agrega todos os vencedores diários em uma matriz, de modo que obtemos uma única linha de resultado por review_window_start . Como alternativa, defina o(s) desempate(s) para obter no máximo um vencedora. Ver: