(func()).*
避免重複函數呼叫當使用傳回表或複合類型的函數時,(func(arg)).*
語法可能會導致每個輸出列的冗餘函數呼叫。 在表或子查詢中呼叫函數時會出現此問題,其中 (func()).*
通常是唯一實用的方法。
意外的是,(func()).*
觸發了多個函數執行-數量等於輸出列數。 例如,傳回四列的函數可能會被呼叫八次,而不是預期的兩次。
要修正此問題,請將函數呼叫封裝在子查詢中:
SELECT (mf).* FROM ( SELECT my_func(x) AS mf FROM some_table ) sub;
這通常可以避免額外的函數調用,並且不會引入額外的運行時掃描。 為了絕對確定,請考慮 OFFSET 0
技巧或利用 PostgreSQL 在 CTE 最佳化方面的限制:
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;
PostgreSQL 9.3 及更高版本提供了更優雅的解決方案,使用 LATERAL
:
SELECT mf.* FROM some_table LEFT JOIN LATERAL my_func(some_table.x) AS mf ON true;
解析器將 (func()).*
擴展為列列表是根本原因。 解析後的樹顯示 (func(x)).*
轉換為:
<code>(my_func(x)).i, (my_func(x)).j, (my_func(x)).k, (my_func(x)).l</code>
這種低效的節點克隆,而不是單一函數呼叫節點複製,導致了重複呼叫。
以上是在 SQL 查詢中使用 `(func()).*` 時如何防止多個函數呼叫?的詳細內容。更多資訊請關注PHP中文網其他相關文章!