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

JOINが重複を返した後のGROUPまたはDISTINCT

    テーブルからすべてまたはほとんどの行を取得する場合、このタイプのクエリの最速の方法は、通常、最初に集計/明確化することです。 後で参加します :

    SELECT *
    FROM   products p
    JOIN  (
       SELECT DISTINCT ON (product_id) *
       FROM   meta
       ORDER  BY product_id, id DESC
       ) m ON m.product_id = p.id;
    

    metaの行数が増える productsの行ごと 、パフォーマンスへの影響が大きくなります。

    もちろん、ORDER BYを追加することをお勧めします サブクエリの句はwhichを定義します サブクエリの各セットから選択する行。 @Craigと@Clodoaldoはすでにそれについてあなたに話しました。 metaを返します idが最も高い行 。

    SQLフィドル。

    DISTINCT ONの詳細 :

    • 各GROUPBYグループの最初の行を選択しますか?

    パフォーマンスを最適化する

    それでも、これが常に最速のソリューションであるとは限りません。データ分散に応じて、他のさまざまなクエリスタイルがあります。別の結合を含むこの単純なケースの場合、これは大きなテーブルを使用したテストでかなり高速に実行されました。

    SELECT p.*, sub.meta_id, m.product_id, m.price, m.flag
    FROM  (
       SELECT product_id, max(id) AS meta_id
       FROM   meta
       GROUP  BY 1
       ) sub
    JOIN meta     m ON m.id = sub.meta_id
    JOIN products p ON p.id = sub.product_id;
    

    わかりにくいidを使用しない場合 列名として、名前の衝突に遭遇することはなく、単にSELECT p.*, m.*と書くことができます。 。 (私は決して idを使用する 列名として。)

    パフォーマンスが最も重要な要件である場合は、より多くのオプションを検討してください。

    • MATERIALIZED VIEW metaから事前に集計されたデータを使用 、データが(大幅に)変更されない場合。
    • ルーズインデックススキャンをエミュレートする再帰CTE 大きいの場合 meta 多くのテーブル 商品ごとの行数(比較的少数の個別のproduct_id )。
      これは、テーブル全体でDISTINCTクエリにインデックスを使用することを私が知っている唯一の方法です。


    1. 自動インクリメントで列の開始値を設定する

    2. psqlで当月の日曜日のカウントを取得するにはどうすればよいですか?

    3. postgreSQLで変数を使用してリターンタイプを指定しないことは可能ですか?

    4. JSONのPostgreSQLインデックス