1. ホーム
  2. sql

[解決済み】PostgreSQLのLATERAL JOINとサブクエリの違いは何ですか?

2022-04-18 08:26:19

質問

Postgresは、このような機能を備えています。 LATERAL 現在、私はチームのために、非効率的なサブクエリを数多く含む複雑なデータダンプを行っており、全体のクエリに4分以上かかってしまうため、このことについて調べています。

私は、以下のことを理解しています。 LATERAL のような記事を読んでも、「この人なら大丈夫」と思える。 これ のHeap Analyticsが、まだよくわからないのです。

のユースケースは何ですか? LATERAL を結合してください。の違いは何ですか? LATERAL joinとsubqueryの違いは何ですか?

どのように解決するのですか?

a LATERAL に参加しますか?

この機能はPostgreSQL 9.3から導入されました。 マニュアル :

に登場するサブクエリ。 FROM は、キーワードを前にして LATERAL . これによって、先行する FROM の項目があります。(ただし LATERAL 各サブクエリが評価されます。 は独立しているので、他の FROM の項目があります)。

に登場するテーブル関数 FROM は、その前にキー 単語 LATERAL しかし、関数の場合、キーワードはオプションです。 関数の引数には、以下の方法で提供されるカラムへの参照を含めることができます。 前の FROM の項目は、どのような場合でも

基本的なコード例はそこに記載されています。

どちらかというと 相関 サブクエリ

A LATERAL の結合は、どちらかというと 相関サブクエリ の右側にある式は、通常のサブクエリではなく、サブクエリになります。 LATERAL は、その左側の行ごとに1回ずつ評価されます。 相関 サブクエリ - 通常のサブクエリ (テーブル式) は、次のように評価されます。 一度だけ のみです。(クエリプランナーには、どちらに対してもパフォーマンスを最適化する方法がありますが)。

同じ問題を解決するために、両者を並べたコード例で関連回答。

を返す場合 複数のカラム , a LATERAL の結合は、通常、よりシンプルでクリーンかつ高速です。

また、相関サブクエリに相当するのは、次のようなものであることを覚えておいてください。 LEFT JOIN LATERAL ... ON true :

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

そこで を使用することができます。 LATERAL joinはできますが、(相関)サブクエリは(簡単には)できません。相関サブクエリは単一の値のみを返すことができ、複数列や複数行を返すことはできません。ただし、素の関数呼び出し(複数行を返す場合は結果行を乗算します)は例外です。しかし、ある種の集合を返す関数でさえも、その関数が使用できるのは FROM 節があります。例えば unnest() は、Postgres 9.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 [, ... ] ) :

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

のようなセットを返す関数も使用できます。 unnest() の中で SELECT のリストを直接表示します。以前は、このような関数が1つ以上あると、驚くような挙動を示しました。 SELECT リストが表示されます。 しかし、Postgres 10でようやくサニタイズされました。 であり、現在では有効な代替手段となっています(標準SQLではないにせよ)。ご覧ください。

上の例の積み重ね。

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

比較する。

dbfiddle - pg 9.6用 これ

pg10用dbfiddle これ

誤報を明らかにする

マニュアルのことです。

については INNEROUTER の場合、ジョインコンディションは のいずれか、すなわち NATURAL , 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;

だからこそ アンドマール のコード例は正しいです。 CROSS JOIN は結合条件を必要としない)と アッティラズ <ストライク でございます はなかった。