【发布时间】:2020-01-31 14:45:12
【问题描述】:
考虑一个简化的例子:
SELECT
lengthy_expression AS a,
g(a) AS b,
h(a) AS c,
...
FROM
my_table
这里,lengthy_expression 表示一个复杂的表达式,它使用来自my_table 的多个字段并跨越多行。其结果用于计算另外两个字段b 和c。但是,在标准SQL中是不允许的,因为WHERE子句中的表达式不允许引用WHERE子句中另一个表达式的结果(为什么不超出我的范围)。
天真的选项是重复lengthy_expression,但这是我明确想要避免的。
一种选择是使用子查询:
SELECT
a,
g(a) AS b,
h(a) AS c,
...
FROM (
SELECT
lengthy_expression AS a,
...
FROM
my_table
)
但正如您所见,我现在需要重复外部查询所需的其他字段 ...。
也许是一个带有连接的子查询?
SELECT
a,
g(a) AS b,
h(a) AS c,
...
FROM
my_table
INNER JOIN (
SELECT
lengthy_expression AS a
FROM
my_table
) USING id
它可以工作,但是现在有一个(可能很昂贵的)连接,除了保持查询可读性之外没有其他用途。而且它甚至不能很好地达到这个目的,因为lengthy_expression 被隐藏在使用它的位置下方,人类读者必须跳遍整个地方才能找出发生了什么。
另一种方法是使用 CTE:
WITH
my_table_with_a AS (
SELECT
*,
lengthy_expression AS a
FROM
my_table
)
SELECT
*,
g(a) AS b,
h(a) AS c,
...
FROM
my_table_with_a
至少现在阅读顺序或多或少与操作发生的逻辑顺序相匹配,但它非常冗长,并且很难为my_table_with_a 找到一个好名字。尤其是因为在实践中,我会重复这种模式两到三遍。
有没有更好的方法来做到这一点?
【问题讨论】:
-
我会使用 CTE。您说它们很冗长,但是与复杂/重复的联接相比,新的代码行相对“便宜”。如果同事(或 6 个月后的您)需要审查您的代码,CTE 的可读性非常好。
标签: sql google-bigquery