【问题标题】:update with many common sub-expressions使用许多常见的子表达式进行更新
【发布时间】:2019-02-22 10:42:36
【问题描述】:

计算一个表的最佳方法是什么,其中许多列是从同一个表中的其他列计算出来的,并且公式以复杂的方式相互构建。

如果您不关心性能,您可以简单地使用自己的更新语句计算每一列:

update x set b1 = a1 + a2;
update x set b2 = a3 * b1;
update x set b3 = a4 * b2;
...

或者,如果您手动扩展公式,您可以在一次更新中完成所有操作:

update x set
  b1 = a1 + a2,
  b2 = a3 * (a1 + a2),
  b3 = a4 * (a3 * (a1 + a2));

这里的问题是这些公式可能会变得庞大且难以更改和调试。

在 Postgres(或者甚至是一般的 SQL)中是否有某种方法可以在这些情况下同时获得性能和可维护性?

这是我希望我能做的事情:

update x set
  b1 = _b1,
  b2 = _b2,
  b3 = _b3
with
  _b1 = a1 + a2,
  _b2 = a3 * _b1,
  _b3 = a4 * _b2;

我有一个可行的解决方案,其中公式在具有多个返回值的函数中定义,但这在某些其他方面相当不灵活,因此我正在寻找替代方案。

【问题讨论】:

  • 我实际上对您当前的方法没有意见,并且不涉及动态 SQL 的解决方法可能比它的价值更多。

标签: postgresql sql-update database-performance code-maintainability


【解决方案1】:

您可以在最新的 PostgreSQL 版本中使用以下内容:

UPDATE atable
SET (col1, col2, col3) =
SELECT expr1, expr2, expr3
FROM ...

如果需要在查询中复用计算表达式,可以使用WITH

WITH t1(x1) AS (
   SELECT /* complicated */
), t2(x2) AS (
   SELECT /* complicated using t1 */
) ...
SELECT /* final results */

我不确定这是否会使代码对您更具可读性,但它避免使用函数并且符合标准(我认为,没有检查)。

【讨论】:

  • 谢谢。我在 Postgres 文档中看到了这一点,但是我不确定如何将其应用于我在单个表中更新而不涉及任何选择的用例。
  • 我的回答只能和你的问题一样具体。
【解决方案2】:

我想出了一些接近我正在寻找的东西:

update x set (b1, b2, b3) = ((
  select b1, b2, b3
  from (select b1, b2, a4 * b2 as b3
  from (select b1, a3 * b1 as b2
  from (select a1 + a2 as b1
  ) as _) as _) as _
));

它仍然比我想要的更冗长,但基本上达到了不必扩展公式,不使用函数的目标。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-13
    • 2013-09-30
    • 2021-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-23
    • 2021-04-05
    相关资源
    最近更新 更多