PostgreSQL中CASE语句重复表达式是否会重复计算?
问题
我此前尝试搜索但未找到答案,特此咨询。现有如下SQL语句:
CASE WHEN p."PlanPeriod_End" >= (CASE WHEN p."FactPeriod_End" IS NULL THEN NOW() ELSE p."FactPeriod_End" END) -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ THEN 'нет' ELSE (CASE WHEN p."FactPeriod_End" IS NULL THEN NOW() ELSE p."FactPeriod_End" END - p."PlanPeriod_End")::TEXT -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ END
如上所示,语句中重复出现了:
CASE WHEN p."FactPeriod_End" IS NULL THEN NOW() ELSE p."FactPeriod_End" END
我的问题是:对于每条记录,该表达式会被计算两次,还是PostgreSQL内部会优化为仅计算一次?即pgSQL是否对此类场景有内置优化,还是需要手动优化?
回答
PostgreSQL会自动优化这种重复的确定性表达式,对于每条记录,这个重复的CASE表达式只会计算一次。
不过有个例外:如果表达式里包含非确定性函数(比如NOW()),PostgreSQL在同一条SQL语句里对同一个非确定性函数的多次调用,结果是相同的,但底层是否会复用计算结果取决于查询优化器的判断。不过在你的场景里,即使NOW()被调用两次,它在同一条语句执行期间返回的时间戳是一致的,所以结果不会有差异。
如果想要彻底避免不确定因素,或者让代码更易读,手动优化也是可行的——可以用LATERAL子查询或者CTE把这个表达式抽出来,示例如下:
用LATERAL子查询优化
SELECT CASE WHEN p."PlanPeriod_End" >= calc."Effective_End" THEN 'нет' ELSE (calc."Effective_End" - p."PlanPeriod_End")::TEXT END AS result FROM your_table p LATERAL ( SELECT CASE WHEN p."FactPeriod_End" IS NULL THEN NOW() ELSE p."FactPeriod_End" END AS "Effective_End" ) calc;
用CTE优化
WITH calc_data AS ( SELECT p.*, CASE WHEN p."FactPeriod_End" IS NULL THEN NOW() ELSE p."FactPeriod_End" END AS "Effective_End" FROM your_table p ) SELECT CASE WHEN "PlanPeriod_End" >= "Effective_End" THEN 'нет' ELSE ("Effective_End" - "PlanPeriod_End")::TEXT END AS result FROM calc_data;
手动优化的好处是让SQL结构更清晰,避免重复代码,后续维护也更方便。
内容的提问来源于stack exchange,提问作者Константин Сиротин
相关产品推荐
相关产品推荐

