sql >> データベース >  >> RDS >> PostgreSQL

動的な一連の日以来、レビュー数が最も多いアプリを入手する

    私は考えます これがあなたが探しているものです:

    Postgres13以降

    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 少し安くなります。 Postgres 13(現在はベータ版)で追加されました。参照:

    Postgres12以前

    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 こちら

    上記と同じですが、WITH TIESはありません 。

    テーブルappsを含める必要はありません まったく。テーブルのreviews 必要なすべての情報があります。

    CTE cte アプリごとの最も早いレビューと現在の合計数を計算します。 CTEは、繰り返しの計算を回避します。かなり役立つはずです。
    これは常にPostgres12の前に具体化され、メインクエリで何度も使用されるため、Postgres12で自動的に具体化される必要があります。それ以外の場合は、キーワードMATERIALIZEDを追加できます。 Postgres12以降でそれを強制します。参照:

    最適化されたgenerate_series() callは、最初のレビューから最新のレビューまでの一連の日を生成します。参照:

    最後に、LEFT JOIN LATERAL あなたはすでに発見しました。ただし、複数のアプリが結びつく可能性がある ほとんどのレビューについては、0〜n個のアプリである可能性があるすべての勝者を取得します。クエリはすべての毎日の勝者を配列に集約するため、review_window_startごとに1つの結果行を取得します 。または、タイブレーカーを定義して、最大で1つを取得します 勝者。参照:



    1. SQL ServerでのSIGN()の例

    2. 同じクエリに対してMySQLWorkbenchはPythonよりもはるかに高速です

    3. MySQLで同等のDATALENGTH()とは何ですか?

    4. エンティティ開発者とADO.NetデータプロバイダーがEntityFrameworkCore5をサポートするようになりました