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

LATERAL JOINとPostgreSQLのサブクエリの違いは何ですか?

    とは LATERAL 参加しますか?

    この機能はPostgreSQL9.3で導入されました。マニュアル:

    FROMに表示されるサブクエリ キーワードLATERALを前に付けることができます 。これにより、先行するFROMによって提供される列を参照できます。 アイテム。 (LATERALなし 、各サブクエリは独立して評価されるため、他のFROMを相互参照することはできません。 アイテム。)

    FROMに表示されるテーブル関数 キーワードLATERALを前に付けることもできます 、ただし、関数の場合、キーワードはオプションです。関数の引数には、前にあるFROMによって提供される列への参照を含めることができます。 いずれにせよアイテム。

    基本的なコード例がそこにあります。

    より相関のように サブクエリ

    LATERAL 結合は、LATERALの右側にある式において、単純なサブクエリではなく、相関サブクエリに似ています。 結合は、その左側の行ごとに1回評価されます-相関のように サブクエリ-プレーンなサブクエリ(テーブル式)が一度評価される間 それだけ。 (ただし、クエリプランナーには、どちらの場合もパフォーマンスを最適化する方法があります。)
    両方のコード例を並べた関連回答で、同じ問題を解決します:

    • GROUP BYクエリを最適化して、ユーザーごとに最新の行を取得します

    複数の列を返す場合LATERAL 通常、結合はより単純で、よりクリーンで、より高速です。
    また、相関サブクエリに相当するものは、 LEFT JOIN LATERAL ... ON trueであることを忘れないでください。

    • 配列引数を使用して集合を返す関数を複数回呼び出す

    サブクエリで実行できないこと

    LATERAL 結合は可能ですが、(相関する)サブクエリは(簡単に)できません。相関サブクエリは、裸の関数呼び出し(複数の行を返す場合に結果の行を乗算する)を除いて、単一の値のみを返すことができ、複数の列や複数の行を返すことはできません。ただし、特定のセットを返す関数でさえ、FROMでのみ許可されます。 句。 unnest()のように Postgres9.4以降では複数のパラメータを使用します。マニュアル:

    これはFROMでのみ許可されています 条項;

    したがって、これは機能しますが、(簡単に)サブクエリに置き換えることはできません:

    CREATE TABLE tbl (a1 int[], a2 int[]);
    SELECT * FROM tbl, unnest(a1, a2) u(elem1, elem2);  -- implicit LATERAL
    

    カンマ(,FROM 句はCROSS JOINの短い表記です 。
    LATERAL テーブル関数では自動的に想定されます。
    UNNEST( array_expression [, ... ] )の特殊なケースについて :

    • FROM句でのみ許可されるset-returning-functionをどのように宣言しますか?

    SELECTのセットリターン関数 リスト

    unnest()のような集合を返す関数を使用することもできます SELECTで 直接リストします。これは、同じSELECT内に複数のそのような関数があるという驚くべき動作を示していました。 Postgres9.6までのリスト。しかし、ついにPostgres 10でサニタイズされ、現在は有効な代替手段です(標準SQLでなくても)。参照:

    • SELECT句で複数のセットを返す関数に期待される動作は何ですか?

    上記の例に基づいて構築:

    SELECT *, unnest(a1) AS elem1, unnest(a2) AS elem2
    FROM   tbl;
    

    比較:

    ここに9.6ページのdbfiddle
    10ページのdbfiddleはこちら

    誤った情報を明確にする

    マニュアル:

    INNERの場合 およびOUTER 結合タイプの場合、結合条件を指定する必要があります。つまり、NATURALの1つだけを指定する必要があります。 、ON join_condition 、またはUSING join_column [、...])。意味については、以下を参照してください。
    CROSS JOINの場合 、これらの句はいずれも表示できません。

    したがって、これら2つのクエリは有効です(特に有用ではない場合でも):

    SELECT *
    FROM   tbl t
    LEFT   JOIN LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t ON TRUE;
    
    SELECT *
    FROM   tbl t, LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t;
    

    これはそうではありませんが:

    SELECT *
    FROM   tbl t
    LEFT   JOIN LATERAL (SELECT * FROM b WHERE b.t_id = t.t_id) t;

    Andomarのコード例が正しいのはそのためです(CROSS JOIN 結合条件は必要ありません)、Attilaの そうではありませんでした。



    1. MySQLチュートリアル:MySQL INステートメント(上級)

    2. JRubyとJDBCを使用してOracleに接続する方法

    3. PostgreSQL:結果のデータをSQLクエリからExcel/CSVにエクスポートします

    4. Oracleでフィールドの値が変更されたときに行番号をインクリメントする