ホームページ >データベース >mysql チュートリアル >SQL クエリで `(func()).*` を使用するときに複数の関数呼び出しを防ぐ方法は?

SQL クエリで `(func()).*` を使用するときに複数の関数呼び出しを防ぐ方法は?

Linda Hamilton
Linda Hamiltonオリジナル
2025-01-10 11:51:42530ブラウズ

How to Prevent Multiple Function Calls When Using `(func()).*` in SQL Queries?

SQL クエリで (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 サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。