Sql 在同一查询中多次使用计算列

Sql 在同一查询中多次使用计算列,sql,postgresql,subquery,common-table-expression,divide-by-zero,Sql,Postgresql,Subquery,Common Table Expression,Divide By Zero,我有一个反复出现的问题,我想使用我在select查询中多次计算的值。这里有一个例子 SELECT complicated_function(x) as foo, another_complicated_function(y) as bar, complicated_function(x)/another_complicated_function(y) as foo_bar_rate FROM my_table; 编写此查询的最简单方法是什么?理想情况下,我想写作 SELECT

我有一个反复出现的问题,我想使用我在select查询中多次计算的值。这里有一个例子

SELECT
  complicated_function(x) as foo,
  another_complicated_function(y) as bar,
  complicated_function(x)/another_complicated_function(y) as foo_bar_rate
FROM my_table;
编写此查询的最简单方法是什么?理想情况下,我想写作

SELECT
  complicated_function(x) as foo
  another_complicated_function(y) as bar,
  foo/bar as foo_bar_rate
FROM my_table;

这个问题不是关于正在计算的特定值,而是关于如何以更简单、更易于维护的方式编写此查询。

您可以将

WITH computed_functions as (
  SELECT
    complicated_function(x) as foo,
    another_complicated_function(y) as bar,
  FROM my_table;
)
SELECT foo, bar, foo/bar as foo_bar_rate FROM computed_functions;

然而,这仍然是笨重的。如果要选择更多列,需要将其添加到WITH查询和主查询。

使用CTE的答案通常是好的。不过,有几点建议:

SELECT *, foo / NULLIF(bar, 0) AS foo_bar_rate  -- defend against div0
FROM  (
   SELECT complicated_function(x)         AS foo
        , another_complicated_function(y) AS bar
   FROM   my_table
   --  OFFSET 0  -- see below
   ) sub;
  • 在Postgres中,CTE(尽管对某些人来说更容易阅读)通常比普通的子查询更昂贵。如果性能相关,则仅在实际需要的地方使用CTE。在这种情况下,你不需要

    Postgres可能会在其查询计划中将子查询展平,如果成本设置和服务器配置良好,这通常也是最好的做法。如果您更清楚(确定?),可以使用未记录的“查询提示”
    偏移量0
    ,这是一种逻辑干扰,但会强制单独执行子查询

  • 要保持代码简短,可以在外部选择中使用
    SELECT*
    。(因为您抱怨,所以必须将所有列添加到主查询。)

  • 用于防御可能被0除的异常-除非
    另一个函数(y)
    永远不能返回
    0


请提供一个表定义(
CREATE table
语句),显示数据类型和约束以及您的Postgres版本。解释一下你到底在数什么。可能有一个更简单/更快的解决方案。这里至少有一个挥之不去的bug。这个问题与我计算的具体值无关。我重写了查询以反映这一点。我正在努力编写更好、更易于维护的SQL。我正在使用PostgreSQL 9.6.2