SELECT
ステートメント内の複数のセットを返す関数による PostgreSQL の予期しない動作問題:
SELECT
ステートメントの句内で複数のセットを返す関数を使用すると、特にセットの長さが等しくない場合、予期しない結果が生じる可能性があります。 generate_series(1, 3)
と generate_series(5, 7)
は相互結合を生成しますが、generate_series(1, 2)
と generate_series(1, 4)
は生成しません。この矛盾は不可解です。
説明:
鍵となるのは、PostgreSQL のバージョンの違いです。 PostgreSQL 10 以降のバージョンでは、以前のバージョン (9.6 以前) とは異なる方法でこれを処理します。
PostgreSQL 10 以降:
PostgreSQL 10 以降のリリースでは、SELECT
リスト内の複数のセットを返す関数を LATERAL ROWS FROM(...)
句と同様に扱います。 関数は同期的に実行され、最も長いセットの長さに一致するように、短いセットには NULL
値が埋め込まれます。これにより、完全な相互結合が保証されます。 例:
<code>row2 | row3 | row4 -----+------+----- 1 | 11 | 21 2 | 12 | 22 NULL | 13 | 23 NULL | NULL | 24</code>
PostgreSQL 9.6 以前:
古いバージョン (9.6 以前) では、結果セットの行数は、個々の関数の行数の最小公倍数 (LCM) と等しかった。 クロス結合は、セットのサイズが公約数を共有しない場合にのみ発生します。 同じ例を使用すると、出力は次のようになります:
<code>row2 | row3 | row4 -----+------+----- 1 | 11 | 21 2 | 12 | 22 1 | 13 | 23 2 | 11 | 24 1 | 12 | 21 2 | 13 | 22 1 | 11 | 23 2 | 12 | 24 1 | 13 | 21 2 | 11 | 22 1 | 12 | 23 2 | 13 | 24</code>
ベストプラクティス:
予期しない結果を避けるには、複数のセットを返す関数を LATERAL
リストに直接配置するのではなく、SELECT
結合またはサブクエリを使用することをお勧めします。これにより、より明確な制御と予測可能な動作が提供されます。
詳細と関連情報については、PostgreSQL の公式ドキュメントを参照してください。
以上がPostgreSQL で、SELECT 句内の複数のセットを返す関数が常にクロス結合を生成するとは限らないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。