来源:http://www.cnblogs.com/gaiyang/archive/2011/04/13/2014356.html

T-SQL查询处理这种逻辑处理顺序,是理论上的处理过程,实际情况还会根据查询优化器选择最优的执行计划。

还是从FROM阶段讲开。

(1)FROM阶段

这个阶段是查询逻辑处理的第一步。想到这里,想起了LINQ表达式不就是从FROM开始的嘛,看来还是挺有道理的。FROM阶段负责表示表或要查询的表。如果指定了表运算符,还需 要按从左到右的顺序,对运算符进行逐个处理。表运算符有4类,JOIN,APPLY,PIVOT,UNPIVOT。每个表运算符都有自己的处理规则。这里挑最常见的JOIN来说。

对于联接(join),一般有以下几个个步骤:

a.求笛卡尔积,对两张表进行cross join,得出最大的可能结果集。如果左表有n行,右表有m行,则结果集有nxm行。

b.利用ON筛选条件来筛选,剔除不符合条件的行。

c.对于外联接(left,right,full outer join),还需要添加外部行。在上个步骤中,ON条件剔除掉了所有不匹配两张表的行。但是在外联接中,通过指定外连接的类型,需要将其中的一个或者两个表标记为保留表,并返回该表中所有的行。所以这时候还需要将保留表中被ON筛选条件剔除的行重新加入到结果集中(这些重新加进来的表,书中称为外部行),并将外部行中非保留表的列值标记为NULL.再次提醒一下,这一个步骤,只有外联接才执行,对于内联接(inner join)只需要执行a和b两个步骤的。

(2)WHERE阶段

对于上一步骤返回的虚拟表,经过where条件的判定,只有让where条件为true的行才会被保留下来。请注意,因为还没有对数据进行分组,所以在where子句中不能聚合。也不能引用select列表中创建的别名,因为SELECT阶段还在后头呢。例如where orderid>max(orderid), select year(thedate) as theyear... where theyear>2010是不能使用的。

另外一个很让人迷惑的问题是,对于包含JOIN的查询,到底ON和WHERE子句有什么区别,应该什么时候使用ON子句,什么时候使用where子句。这里作一下说明。只有对于外联接,ON和where子句才会存在这种逻辑区别,因为在外联接中,通过ON子句的筛选之后,还要对保留表进行外部行添加,而where子句则是在外部行添加过之后才进行筛选的。因此,ON子句对这种外联接的情况的筛选,并不是最终的结果,在FROM阶段的第三个步骤,还会把外部行添加回来的。而对于内联接,where子句和on子句作用是完全一样的,在哪里筛选都是同种效果,没有其他步骤。所以在处理这种含有外联接的查询,一定要注意ON筛选和where筛选的区别,避免使用错了,达不到筛选的效果。另外,对于内联接,一个不错的建议是,对于两个表都存在的字段筛选,用ON子句,对于单个表的字段筛选,用where,例如:select * from a inner join b on a.col = b.col where a.col2 >1。

(3)GROUP BY阶段

在这一阶段将上一步返回的虚拟表中的结果集按分组进行重组,由分组集所有列的每个唯一组合,标识出一个组。再用这些组,跟上一步返回的每一个行进行关系。注意,每个行只能关联一个组。最后,生成的结果集中,每个组只能有一行。关于GROUP BY还有很多有意思的地方,比如cube,rollup,grouping等等,有时间再一一介绍。

(4)HAVING阶段

HAVING筛选器用于对上一步返回的结果集进行筛选。HAVING筛选器是唯一能筛选分组数据的筛选器,ON和where都不行。理由很简单,ON和where都是在分组之前进行处理的,自然不能对分组进行筛选。所以HAVING和WHERE的区别,也是很显而易见了。HAVING 只能与 SELECT 语句一起使用。HAVING 通常在 GROUP BY 子句中使用。如果不使用 GROUP BY 子句,则 HAVING 的行为与 WHERE 子句一样。

(5)SELECT阶段

这一个步骤,将构造最终返回给调用者的表。这个步骤涉及到3个子阶段。

a.计算表达式。在这个阶段中,select列表可以返回油上一步得到的虚拟表的基础列,也可以是对这些基础列的操作。有一点需要注意的是,在这个select列表中,所有的表达式是同时计算的。举个例子,在SQL中,可以这么交换两个列值:update tab_test set col1 = col2,col2 =col1;在别的语言看来这的确很神奇。

而且在select列表中创建的别名不能在同一select列表中的其他表达式中使用。所以,基于这个特性,我们就会得出一个结论,select列表的顺序是无关紧要的。

b.处理DINSTINCT,如果查询中指定了DINSTINCT,则从上一步返回的虚拟表中删除重复的行。

c.应用TOP选项。对于指定了TOP选项的查询,则会根据查询的order by子句来选择指定数量的行。TOP选项里有很多特殊的地方,此处先不扯远,以后有机会单独讲。

(6)ORDER BY阶段

这一步按照order by列表中的列明对上一步的表进行排序,返回游标。

这里有必要谈一下集合和游标。SQL的理论基础是集合,集合是无序的,它只是成员的一种逻辑集合。对于带有排序作用的ORDER BY子句的查询,可以返回一个对象,其中的行按照特定的顺序组织在一起。ANSI把这种 对象成为游标(cursor)。

因为在这一步中,最后返回的是游标,所以带有order by的查询,是不能用来定义视图,子查询,公用表等。例如:

SELECT * FROM (SELECT col1,col2 FROM tab_test ORDER BY col1)是无效的,并且将报错。

但是如果同时指定了TOP选项,则是一个例外。SELECT * FROM (SELECT top (10) col1,col2 FROM tab_test ORDER BY col1),对于这个查询,因为同时指定了top和order by,则子查询中的结果一定是固定而且有序的的,但是外部的查询,则不能保证是有序排列的。

对于T-SQL查询逻辑处理,就整理到这里,有什么问题,还请大家指出,一起探讨。

Tsql查询执行顺序(二)的更多相关文章

  1. Tsql查询执行顺序

    对于T-SQL编程,用得最广泛的,莫过于查询(Querying).要想写出高质量.高性能的查询语句,必须深入地了解逻辑查询处理. 一.逻辑查询处理的各个阶段 (5)SELECT DISTINCT TO ...

  2. T-sql语句查询执行顺序

    前言 数据库的查询执行,毋庸置疑是程序员必备技能之一,然而数据库查询执行的过程绚烂多彩,却是很少被人了解,今天哥哥要带你装逼带你飞,深入一下这sql查询的来龙去脉,为查询的性能优化处理打个基础,或许面 ...

  3. [转载]T-SQL(Oracle)语句查询执行顺序

    原文链接:http://blog.sina.com.cn/s/blog_61c006ea0100mlgq.html sql语法的分析是从右到左,where子句中的条件书写顺序,基本上对sql性能没有影 ...

  4. [转载]T-SQL(MSSQL)语句查询执行顺序

    注意:笔者经过实验和查阅资料,已在原作基础上做了部分更改.更改不代表原作观点,查看原作请点击下方链接. 原文出处: 作者:张龙豪 链接:http://www.cnblogs.com/knowledge ...

  5. SQL server T-sql语句查询执行顺序

    前言 数据库的查询执行,毋庸置疑是程序员必备的技能之一,然而数据库查询执行的过程绚烂多彩,却是很少被人了解,今天我们来深入了解下sql查询的来龙去脉,为查询的性能优化打个基础 这篇博客,摒弃查询优化性 ...

  6. Select查询执行顺序

    链接:http://blog.jobbole.com/55086/ 很多程序员视 SQL 为洪水猛兽.SQL 是一种为数不多的声明性语言,它的运行方式完全不同于我们所熟知的命令行语言.面向对象的程序语 ...

  7. T-SQL 之 执行顺序

    1.sql查询语句的处理步骤,代码清单 --查询组合字段 (5)select (5-2) distinct(5-3) top(<top_specification>)(5-1)<se ...

  8. sql 语句 嵌套子查询 执行顺序分析

    --创建测试数据create table Student(S# varchar(10),Sname nvarchar(10),Sage datetime,Ssex nvarchar(10))inser ...

  9. sql语句查询执行顺序

    http://blog.csdn.net/bitcarmanlee/article/details/51004767

随机推荐

  1. Python为什么不隐式实现self

    Python为什么不隐式实现self Python中类的方法都需要显式的传入一个self占位参数,这让写过C#,Java,PHP,Javascript的我很是不习惯,但是Python这么吊,肯定是有他 ...

  2. 练习2 练习目标-使用引用类型的成员变量:在本练习中,将扩展银行项目,添加一个(客户类)Customer类。Customer类将包含一个Account对象。

    package banking; public class Customer { private String firstName; private String lastName; private ...

  3. Android线程处理

    对JAVA的线程相信大家都有一定的认识,本篇就让我们一起探讨一下Android中的线程问题,对于线程和进程的区别我就不再赘述,有兴趣的小童鞋可以百度一下,讲解的非常详细,相信大家经常可以听到关于线程的 ...

  4. Uvaoj 10048 - Audiophobia(Floyd算法变形)

    1 /* 题目大意: 从一个点到达另一个点有多条路径,求这多条路经中最大噪音值的最小值! . 思路:最多有100个点,然后又是多次查询,想都不用想,Floyd算法走起! */ #include< ...

  5. 后端码农谈前端(CSS篇)第四课:选择器补充(伪类与伪元素)

    一.伪类: 属性 描述 :active 向被激活的元素添加样式. :focus 向拥有键盘输入焦点的元素添加样式. :hover 当鼠标悬浮在元素上方时,向元素添加样式. :link 向未被访问的链接 ...

  6. 设为首页 和 收藏本站js代码 兼容IE,chrome,ff

    设为首页 和 收藏本站js代码 兼容IE,chrome,ff //设为首页 function SetHome(obj,url){ try{ obj.style.behavior='url(#defau ...

  7. 使用AsyncTask异步更新UI界面及原理分析

    概述: AsyncTask是在Android SDK 1.5之后推出的一个方便编写后台线程与UI线程交互的辅助类.AsyncTask的内部实现是一个线程池,所有提交的异步任务都会在这个线程池中的工作线 ...

  8. Kylin的cube模型

    1. 数据仓库的相关概念 OLAP 大部分数据库系统的主要任务是执行联机事务处理和查询处理,这种处理被称为OLTP(Online Transaction Processing, OLTP),面向的是顾 ...

  9. Elasticsearch增删改查 之 —— Delete删除

    删除文档也算是常用的操作了...如果把Elasticsearch当做一款普通的数据库,那么删除操作自然就很常用了.如果仅仅是全文检索,可能就不会太常用到删除. Delete API 删除API,可以根 ...

  10. Akka to .NET

    Akka.NET Current Roadmap Akka.NET is a community-driven port of the popular Java/Scala framework Akk ...