标签:
logical query processing
前言
Transact-SQL 是ANSI和ISO SQL 标准的Microsoft SQL server方言或扩展。
1.1 逻辑查询处理的各个阶段
1.1.1逻辑查询处理阶段简介
(1) from :from阶段标识出查询的来源表。处理表运算符。每个表运算符也会应用一系列子阶段。例如,在联接运算中涉及的阶段是(1-J1)笛卡尔积、(1-J2)on筛选器和(1-J3)添加外部行。from阶段生成虚拟表VT1。
(1-J1)笛卡尔积:这个阶段对表运算符涉及的两个表执行笛卡尔积(交叉联接),生成虚拟表VT1-J1.
(1-J2)ON 筛选器:这个阶段对VT1-J1中的行根据on 子句(<on_predicate>)中出现的谓词进行筛选。只有让该谓词取值为true的行,才能插入VT1-J2中。
(1-J3)添加外部行:如果指定了outer join(相对于cross join或inner join ),则将保留表(preserved table)中没有找到匹配的行,作为外部行添加到VT1-J2,生成VT1-J3.
(2) where:这个阶段根据在where子句中出现的谓词(<where_predicate>)对VT1中的行进行筛选。只有让谓词计算结果为true的行,才会插入VT2中。
(3) group by: 按照group by 子句中指定的列名列表,将VT2中的行进行分组,生成VT3。最终,每个分组只有一个结果行。
(4) having:根据having子句中出现的谓词(<having_predicate>)对VT3中的分组进行筛选。只有让谓词计算结果为TRUE的组,才会插入到VT4中。
(5) select:处理select子句中的元素。生成VT5。
(5-1)计算表达式: 计算select 列表中的表达式,生成VT5-1.
(5-2) distinct:删除VT5-1中的重复行,生成VT5-2.
(5-3)top:根据order by 子句定义的逻辑排序,从VT5-2中选择前面指定数量或百分比的行,生成表VT5-3.(如果没有order by,则top的顺序应该是存储的顺序?)
(6)order by:根据order by子句中指定的列名列表,对VT5-3中的行进行排序,生成游标VC6.
1.3 逻辑查询处理阶段详解
1.3.1 步骤1 FROM阶段
三种筛选器:on、where、having
注意:如果from子句中又多个表运算符,则按从左到右的顺序进行处理,每个表运算符的结果作为下一个表运算符的左输入,最终生成的虚拟表将作为下一阶段的输入。
三值逻辑:(Three-valued logic) 定义:在sql中谓词(逻辑表达式)的可能取值为true、false、unknown,这就是所谓的三值逻辑,是sql特有的属性。 大多数编程语言中的逻辑表达式只有true和false两种取值。sql中的unknown逻辑值通常出现在涉及null值的逻辑表达式中(例如,以下这三个表达式的逻辑值都是unknown:null>2、null=null和x+null>y ).null这个符号代表一种缺失的值。当把一个缺失的值和另一个值(这个值也可能是null)进行比较时,逻辑结果总是unknown。 unknown逻辑结果和null的处理非常容易引起混淆。虽然not true等于false,not false 等于true,但unknown的反面(not unknown)仍然是unknown。 在不同的语言元素中,unknown逻辑结果和null 的处理方式也不尽相同。例如:所有的查询筛选器(on、where、having)都把unknown当做false处理。使筛选器取值为unknown的行会被排除在结果之外。而check约束中的unknown值实际上被当做true对待,假设表中包含一个check约束,要求salary列的值必须大于0.向该表插入salary为nnull的行时也可以成功。因为(null>0)等于unknown,在check约束中按true来处理。 在筛选器中比较两个null值将得到unknown,而unknown按false来处理,就好像其中这两个null不相等一样。 而另一方面,在unique约束、集合运算(如union和except)、以及排序和分组操作中,认为两个null是相等的。 (1)如果表中又一列定义了unique约束,将无法向表中插入该列为null的两行。T-SQL在这一点上与标准不符。 (2)group by子句会将所有null值分到一组。 (3)order by子句会将所有null值排列到一起。 |
1.3.2 步骤2:where阶段
警告:因为还没有对数据进行分组,所以在where子句中不能使用聚合,例如,不能使用where orderdate=max(orderdate),也不能引用select列表中创建的别名,因为select列表这时还未被处理,例如,不能使用select year(orderdte) as orderyear。。。 where orderyear>2008.
对于包含outer join 子句的查询,一个让人感到困惑的问题是:到底应该在on筛选器还是在where筛选器中指定逻辑表达式?
两者的主要区别是on筛选器在添加外部行(步骤1-j3)之前应用,而在where筛选器则是在步骤(1-J3)之后才应用。on筛选器对保留表中部分行的删除并不是最终的,因为步骤(1-J3)会把这些行再添加回来,相反,where筛选器对行的删除时最终的,牢记这一点,将有助于做出正确的选择。
标签:
原文地址:http://www.cnblogs.com/free-birds/p/4593122.html