【问题标题】:Logical Processing Order or SQL Standard in WHERE clauseWHERE 子句中的逻辑处理顺序或 SQL 标准
【发布时间】:2014-03-21 06:47:42
【问题描述】:

几天前有人问我关于 SELECT 语句的逻辑处理顺序,更具体地说是关于别名和 where 子句的问题,我不确定一个问题。如果我们有这样的查询:

SELECT name AS first_name
FROM people
WHERE first_name = 'Alan';

WHERE 子句中使用别名会产生错误的原因实际上是 SELECT 语句的逻辑处理顺序,或者更确切地说是语法解析问题,或者可能是 SQL 标准的规则?

【问题讨论】:

    标签: sql postgresql select where-clause sql-standards


    【解决方案1】:

    这是来自 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 中的列别名。这是因为selectwhere 之后(逻辑上)被评估。所以,当你说:

    select row_number() over (order by a) as seqnum
    from t
    where a > 100
    

    返回的值从第一个a开始 100 之后。枚举不会首先发生,过滤后的行获得被过滤掉的序列号。

    【讨论】:

    • 我同意戈登的观点。评估别名也是在解析时进行的,而不是运行时。习惯于命令式/过程式语言的开发人员难以理解的一个概念是查询的关系性质。顺序并不重要,并且引擎最终会给出关于如何处理它的最终决定,例如,如果您要连接两个表并过滤首先发生的情况是 filterA、filterB 还是 matchAB?答:引擎不好决定。
    猜你喜欢
    • 1970-01-01
    • 2022-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-22
    • 2014-12-25
    • 2012-06-24
    相关资源
    最近更新 更多