ホームページ >データベース >mysql チュートリアル >SQL クエリで `(func()).*` を使用するときに複数の関数呼び出しを防ぐ方法は?
(func()).*
を使用して関数呼び出しの繰り返しを回避するテーブルまたは複合型を返す関数を使用する場合、(func(arg)).*
構文により、出力列ごとに冗長な関数呼び出しが発生する可能性があります。 この問題は、テーブルまたはサブクエリ内で関数を呼び出すときに発生します。多くの場合、(func()).*
が唯一の実用的なアプローチです。
予期せず、(func()).*
は複数の関数の実行 (出力列数と同じ数) をトリガーします。 たとえば、4 つの列を返す関数は、予想される 2 回ではなく 8 回呼び出される可能性があります。
これを修正するには、関数呼び出しをサブクエリ内にカプセル化します。
<code class="language-sql">SELECT (mf).* FROM ( SELECT my_func(x) AS mf FROM some_table ) sub;</code>
これにより、通常、余分な関数呼び出しが回避され、追加のランタイム スキャンが発生することはありません。 絶対確実にするには、OFFSET 0
のトリックまたは CTE 最適化における PostgreSQL の制限を活用することを検討してください。
<code class="language-sql">SELECT (mf).* FROM ( SELECT my_func(x) AS mf FROM some_table OFFSET 0 ) sub; WITH tmp(mf) AS ( SELECT my_func(x) FROM some_table ) SELECT (mf).* FROM tmp;</code>
PostgreSQL 9.3 以降のバージョンでは、LATERAL
:
<code class="language-sql">SELECT mf.* FROM some_table LEFT JOIN LATERAL my_func(some_table.x) AS mf ON true;</code>
パーサーによる (func()).*
の列リストへの展開が根本的な原因です。 解析されたツリーから、(func(x)).*
が次のように変換されることがわかります。
<code>(my_func(x)).i, (my_func(x)).j, (my_func(x)).k, (my_func(x)).l</code>
単一の関数呼び出しノードのレプリケーションではなく、この非効率的なノードの複製により、呼び出しが繰り返されることになります。
以上がSQL クエリで `(func()).*` を使用するときに複数の関数呼び出しを防ぐ方法は?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。