Microsoft Sql Server 2008技术内幕:T-SQL 查询【第一章 逻辑查询处理(20150622)】

注:本文是自己学习摘要,以便后面查询,无其他目的!

 

 

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筛选器对行的删除时最终的,牢记这一点,将有助于做出正确的选择。(提示:只有当使用外联结时,on和where子句才会存在这种逻辑区别,当使用内联接时,在哪里指定逻辑表达式都一样,因为将会跳过步骤3,。在彼此相连的两个步骤中应用这些筛选器,中间没有其他任何步骤。)

 1.3.3 步骤3:group by 阶段

          这个阶段认为两个null值时相等的。也就是说,所有的null值会被分到同一组,就像一个已知的确定值一样。

 1.3.4 步骤4:having 阶段

          注意:count(*)会把外部行统计在内,即包含null值。故应指定列,count(orderid),这样就是准确的统计出每个客户的订单数。

 1.3.5 步骤5:select 阶段

          这里有一个同时操作的概念:例如,在大多数编程环境中,为了交换两个变量值,需要使用一个临时变量,而在sql中交换两个列值时,可以使用:

          update dbo.T1 set c1=c2,c2=c1,从逻辑上来说,应该假设所有操作是同时发生的。就好像是在整个操作完成之前,没有修改过表。接着再用计算结果替换原来的列值,基于类似的原因,以下update语句将更新T1中的所有行,为c1列加上更新开始时T1中的最大的c1值:update dbo.T1 set c1=c1+(select max(c1) from dbo.t1 );不用担心最大的c1值会随着操作的进行而持续变化,因为操作是同时瞬间发生的。

          top选项:百分比是向上取整。

在top中有一个选项:with ties ,指定从基本结果集中返回额外的行,对于 ORDER BY 列中指定的排序方式参数,这些额外的返回行的该参数值与 TOP n (PERCENT) 行中的最后一行的该参数值相同。只能在 SELECT 语句中且只有在指定了 ORDER BY 子句之后,才能指定 TOP...with ties。

 1.3.6 步骤6:排序用的order by 阶段

         该阶段可以用select中的别名,即别名处理是在select 阶段。

        这一步,与其他所有步骤不同的是,它返回的不是一个有效的表,而是一个游标。sql 的理论基础是集合论。集合中的行之间没有预先定义的顺序,它只是成员的一种逻辑组合,成员之间的顺序无关 紧要。对于带有排序作用的order by子句的查询,可以返回一个对象,其中的行按特定的顺序组织在一起。ANSI把这种对象称为游标(cursor)。理解这一步是正确理解sql 最基本的步骤之一。

        表表达式:包括视图、内联表值函数、派生表、cte。在sql中,表表达式中不允许使用带有ordere by子句的查询。而在T-SQL中,这一规定有一个例外,如果同时指定了top选项。

        记住:不要为表中的行假设任何特定的顺序。

        order by 子句认为两个null值是相等的。

1.4  逻辑查询处理的深入内容

  1.4.1 表运算符

   sql 2008中支持4种在查询的from子句使用的表运算符:join、apply、pivot、unpivot。注意,apply、pivot、unpivot不是ANSI标准运算符,它们是T-SQL中特种的扩展。

  1.4.3 集合运算符

   sql 2008支持4种集合运算符:union all、union、except、intersect。

 

posted @ 2015-06-22 12:15  free-bird  阅读(175)  评论(0编辑  收藏  举报