几天前我被问到有关SELECT语句的逻辑处理顺序,更具体地说是关于别名和where子句的问题,我不确定一个问题。如果我们有这样的查询:
SELECT name AS first_name
FROM people
WHERE first_name = 'Alan';
WHERE子句中使用别名会产生错误的原因实际上是SELECT语句的逻辑处理顺序,或者说是语法解析问题,还是SQL标准的规则?
答案 0 :(得分:3)
这是SQL标准的规则(相当复杂,因为它涉及到SQL用户可能没有想到的许多细节)。
该规则背后有两个原则。第一个是标准没有强制执行操作的顺序,除非在逻辑上是必要的(例如,having
子句必须在group by
之后进行逻辑处理)。这是SQL概念的基础,是描述性语言,其中描述了结果。任何特定的数据库引擎都可以确定自己的执行路径。
第二个原则是避免含糊不清。这就是作用域规则的来源,它定义了SQL编译器何时知道。
请考虑以下声明:
select a as b, b as a, a + 1 as d
-----------------------^
from t
问题是:a
a+1
引用的是哪个,a
列中的列b
还是列a
(别名为select
)select
。根据标准,这是明确的。列别名在定义它们的where
子句中是未知的。
这也扩展到select a as b, b as a, a + 1 as d
from t
where a > 100
子句,它在同一范围内进行评估。考虑相同的例子:
a
where
条件引用哪个where
?标准是明确的。 select
子句不理解select
中的列别名。这是因为在where
之后select row_number() over (order by a) as seqnum
from t
where a > 100
被(逻辑上)评估。所以,当你说:
a
返回的值从 100之后的第一个{{1}} 开始。枚举不会先发生,过滤的行会得到过滤掉的序列号。