这是来自 SQL 标准的规则(相当复杂,因为它涉及到许多 SQL 用户可能不会考虑的细节)。
规则背后有两个原则。首先是该标准不强加操作的顺序,除非在逻辑上必要时(例如,having 子句必须在group by 之后进行逻辑处理)。这是 SQL 概念的基础,它是一种描述性语言,其中描述了结果。任何特定的数据库引擎都可以确定自己的执行路径。
第二个原则是避免歧义。这就是作用域规则的用武之地,它定义了 SQL 编译器何时知道。
考虑以下语句:
select a as b, b as a, a + 1 as d
-----------------------^
from t
问题是:a+1 指的是哪个a,表中的a 列或select 中的b 列(别名为a)。根据标准,这是明确的。列别名在定义它们的select 子句中未知。
这也扩展到where 子句,它在同一范围内进行评估。考虑同样的例子:
select a as b, b as a, a + 1 as d
from t
where a > 100
where 条件指的是哪个a?标准是明确的。 where 子句不理解 select 中的列别名。这是因为select 在where 之后(逻辑上)被评估。所以,当你说:
select row_number() over (order by a) as seqnum
from t
where a > 100
返回的值从第一个a开始在 100 之后。枚举不会首先发生,过滤后的行获得被过滤掉的序列号。