とは 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つだけを指定する必要があります。 、ONjoin_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のは そうではありませんでした。