【问题标题】:PostgreSQL reusing value from long calculation in CASE statementPostgreSQL 在 CASE 语句中重用长计算中的值
【发布时间】:2016-04-16 04:40:28
【问题描述】:

我有以下几点:

SELECT
 CASE column1
  WHEN some_long_calc THEN 10
  ELSE some_long_calc + 2*PI
  END AS mycalc,

如何将some_long_calc“保存”为局部变量,这样我就不需要运行两次了?

我正在使用atan2,我希望将角度范围保持在 0 到 2pi 之间

【问题讨论】:

标签: sql postgresql case


【解决方案1】:

首先,我猜查询优化器足够聪明,可以发现相同的确定性表达式并且不会计算两次。

如果这不适用,您可以使用LATERAL:

SELECT *,
  CASE column1
     WHEN sub.long_calc THEN 10
     ELSE sub.long_calc + 2 * 3.14
  END AS mycalc
FROM tab t
,LATERAL (VALUES(t.a+t.b+t.c)) AS sub(long_calc);

SqlFiddleDemo

输出:

╔═════╦══════════╦════╦════╦════╦════════════╦════════╗
║ id  ║ column1  ║ a  ║ b  ║ c  ║ long_calc  ║ mycalc ║
╠═════╬══════════╬════╬════╬════╬════════════╬════════╣
║  1  ║       6  ║ 1  ║ 2  ║ 3  ║         6  ║ 10     ║
║  2  ║      20  ║ 2  ║ 3  ║ 4  ║         9  ║ 15.28  ║
╚═════╩══════════╩════╩════╩════╩════════════╩════════╝

您可以将VALUES 替换为简单的SELECT 或函数调用:

-- any query
,LATERAL (SELECT t.a+t.b+t.c) AS sub(long_calc)
-- function
,LATERAL random() AS sub(long_calc)
-- function with parameter passing
,LATERAL sin(t.a) AS sub(long_calc)

SqlFiddleDemo2


编辑:

SELECT id
      ,sub2.long_calc_rand     -- calculated once
      ,random() AS rand        -- calculated every time
FROM tab t
,LATERAL random() AS sub2(long_calc_rand);

SqlFiddleDemo3

输出:

╔═════╦═════════════════════╦════════════════════╗
║ id  ║   long_calc_rand    ║        rand        ║
╠═════╬═════════════════════╬════════════════════╣
║  1  ║ 0.3426254219375551  ║ 0.8861959744244814 ║
║  2  ║ 0.3426254219375551  ║ 0.8792812027968466 ║
║  3  ║ 0.3426254219375551  ║ 0.8123061805963516 ║
╚═════╩═════════════════════╩════════════════════╝

【讨论】:

  • 计算本身就像 15 行,所以看起来很难看:D
  • @DaynaJuliana 这就是为什么LATERAL 很好。您必须放置一次丑陋的代码:)
  • 这太棒了! VALUES 有必要吗?
  • @DaynaJuliana 是的,您也可以使用函数并从主查询中传递参数 :)
  • 你可以把它放在最后一个JOIN之后。如果您有多个复杂的连接,使用子查询/CTE 将它们“组合”成一个
猜你喜欢
  • 2022-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-11
相关资源
最近更新 更多