理解T-SQL的逻辑查询顺序是学习SQL Server的基础。

  T-SQL逻辑执行顺序

  (8)    SELECT (9) DISTINCT (11) <TOP_specification> <select_list>
  (1)    FROM <left_table>
  (3)        <join_type> JOIN <right_table>
  (2)            ON <join_condition>
  (4)    WHERE <where_condition>
  (5)    GROUP BY <group_by_list>
  (6)    WITH {CUBE | ROLLUP}   
  (7)    HAVING <having_condition>
  (10)   ORDER BY <order_by_list>

  注释

  (1) 执行笛卡尔乘积。如果有多个表JOIN, 则逻辑执行顺序可以理解成: 先执行INNER JOIN, 再执行OUTER JOIN;或者理解成:按表出现的顺序逐个JOIN。当然,实际的执行顺序有赖于实际的执行计划,同一个SQL在不同的“环境”(索引、统计信息等)下,可能产生不同的执行计划。SQL Server的JOIN方式包括:INNER JOIN,LEFT JOIN,RIGHT JOIN,,FULL JOIN,CROSS JOIN,还有值得一提表运算符APPLY:CROSS APPLY,OUTER APPLY。

  (2) 应用ON筛选器。注意把过滤条件放在ON和放在WHERE中的区别: 对于INNER JOIN,过滤条件放在哪里结果都正确;对于OUTER JOIN就要注意了:放在ON中,就是先过滤再JOIN,放在WHERE中,就是先JOIN再过滤,得到的结果很可能是不一样的。当然,生成实际的执行计划时,优化器会自动根据实际情况,把SQL中的LEFT JOIN改成INNER JOIN联接,但是,我的建议是:写SQL时,用INNER JOIN还是LEFT JOIN一定要依据实际的业务逻辑。在此还要注意一下三值逻辑:在筛选器中UNKNOW=FALSE, 在CHECK约束中UNKNOW=TRUE,UNIQUE约束, 排序操作和分组操作认为两个NULL是相等的。

  (3) 添加外部行。外部联接包含: LEFT,RIGHT,FULL。为了说明“添加外部行”的概念,举个例子:A表有4行记录,B表有3行记录,且与A表中的3行记录一一对应。当A表LEFT JOIN B表时,它们实际上进行了两步操作:1.先INNER JOIN,结果产生3行记录,2.添加外部行:把A表中那1行没有与B表对应的记录“添加”到结果集末尾,最终结果集为4行记录。所以,大家经常说INNER JOIN比LEFT JOIN效率高,原因也就在于此,LEFT JOIN多了一个添加外部行的操作。

  (4) 应用WHERE筛选器。再次注意过滤条件放在ON和放在WHERE中的区别:ON在第(2)步被应用, 而WHERE是在第(4)步被应用。

  (5) 分组。注意SELECT语句和GROUP语句中的分组字段或表达式要一致,在不影响分组逻辑的前提下,也允许出现小小的不一致,如: SELECT YEAR(orderdate)+1 FROM table_name GROUP BY YEAR(orderdate)。如果用GROUP BY ALL(非标准遗留物),则相当于跳过第(4)步WHERE过滤,测试时可以一用。

  (6) 应用CUBE或ROLLUP。注意GROUPING聚合函数在这里的应用:如果是由CUBE或ROLLUP产生的NULL,返回1,否则0。

  (7) 应用HAVING筛选器。注意COUNT(*)、COUNT(1)和COUNT(field_name)的区别:前两者无区别,COUNT(field_name)统计时忽略值为NULL的记录。

  (8) 处理SELECT列表。注意某些函数只会产生一个值,如GETDATE(),某些函数函数会产生多个值,如NEWID()。

  (9) 应用DISTINCT子句。注意DISTINCT应该在TOP之前。

  (10)应用ORDER BY子句。唯一一个可利用SELECT列列表中的别名的地方。如果有DISTINCT关键字, ORDER BY中只能出现SELECT列列表中的列。ORDER BY中可以使用数字代表SELECT列表中出现的列,但不推荐。因为ORDER BY只返回游标,所以结果不能用作表表达式(视图、内联表值函数、子查询、派生表、CTE), 但带TOP的选项除外,因为使用TOP后将返回一个结果集, 而并非游标:SELECT * FROM (SELECT TOP(10) * FROM dbo.table_name ORDER BY id DESC) T

  (11)应用TOP选项。可以使用WITH TIES,但必须有ORDER BY:除了返回指定条数的记录,再返回与最后一条记录排序相等的所有记录。TOP()中的参数可以是表达式。如果不指定ORDER BY,查询结果顺序将是不确定的,因为生成的执行计划可能不一样,返回的行是SQL Server物理上最先访问到的行。所以说:有赖于排序的结果集一定要加上ORDER BY。

  小结

  当你写的SQL语法或结果集出现问题时,仔细分析一下T-SQL逻辑执行顺序,就会明白为什么^_^

T-SQL逻辑查询的更多相关文章

  1. 45、SQL逻辑查询语句执行顺序

    一 SELECT语句关键字的定义顺序 SELECT DISTINCT <select_list> FROM <left_table> <join_type> JOI ...

  2. 第四篇:记录相关操作 SQL逻辑查询语句执行顺序

    http://www.cnblogs.com/linhaifeng/articles/7372774.html 一 SELECT语句关键字的定义顺序 SELECT DISTINCT <selec ...

  3. SQL逻辑查询语句执行顺序

    阅读目录 一 SELECT语句关键字的定义顺序 二 SELECT语句关键字的执行顺序 三 准备表和数据 四 准备SQL逻辑查询测试语句 五 执行顺序分析 一 SELECT语句关键字的定义顺序 SELE ...

  4. 9、SQL逻辑查询语句执行顺序

    本篇导航: SELECT语句关键字的定义顺序 SELECT语句关键字的执行顺序 准备表和数据 准备SQL逻辑查询测试语句 执行顺序分析 一.SELECT语句关键字的定义顺序 SELECT DISTIN ...

  5. SQL逻辑查询语句执行顺序 需要重新整理

    一.SQL语句定义顺序 1 2 3 4 5 6 7 8 9 10 SELECT DISTINCT <select_list> FROM <left_table> <joi ...

  6. {MySQL的逻辑查询语句的执行顺序}一 SELECT语句关键字的定义顺序 二 SELECT语句关键字的执行顺序 三 准备表和数据 四 准备SQL逻辑查询测试语句 五 执行顺序分析

    MySQL的逻辑查询语句的执行顺序 阅读目录 一 SELECT语句关键字的定义顺序 二 SELECT语句关键字的执行顺序 三 准备表和数据 四 准备SQL逻辑查询测试语句 五 执行顺序分析 一 SEL ...

  7. mysql SQL 逻辑查询语句和执行顺序

    关键字的执行优先级(重点) fromwheregroup byhavingselectdistinctorder bylimit 先创建两个表 CREATE TABLE table1 ( custom ...

  8. sql逻辑查询语句的执行顺序

    SELECT语句关键字的定义顺序 SELECT DISTINCT <select_list> FROM <left_table> <join_type> JOIN ...

  9. SQL学习笔记四(补充-1-1)之MySQL单表查询补充部分:SQL逻辑查询语句执行顺序

    阅读目录 一 SELECT语句关键字的定义顺序 二 SELECT语句关键字的执行顺序 三 准备表和数据 四 准备SQL逻辑查询测试语句 五 执行顺序分析 一 SELECT语句关键字的定义顺序 SELE ...

  10. mysql五补充部分:SQL逻辑查询语句执行顺序

    一 SELECT语句关键字的定义顺序 SELECT DISTINCT <select_list> FROM <left_table> <join_type> JOI ...

随机推荐

  1. java byte to hex

    String str; byte[] bs = null; bs =str.getBytes(); bs =str.getBytes("utf-8") java  byte to ...

  2. U3D 代码自动化生成定制预置体的旋转问题

    //定制预置体 //要求:1,模型面向U3D的Z轴正向(由MAX导出时是面向U3D的X负向的) //2,增加一些常用挂点,3增加一个圆形阴影片,4,添加包围盒 //根据这些要求制作预置休 static ...

  3. js添加对象数组

    json 数组也是数组  var jsonstr="[{'name':'a','value':1},{'name':'b','value':2}]"; var jsonarray  ...

  4. C#异步编程的一些认识

    1.使用委托类型的BeginXXX,EndXXX 2.使用事件 3.使用aysnc,await关键字,会自动切换回UI线程,启动方法的线程可以被重用,线程没有阻塞.内部其实是封闭了Task类的Cont ...

  5. 关于PHP如何用实现防止用户在浏览器上使用后退功能重复提交输入

    $(function(){ if(window.history && window.history.pushState){ $(window).on('popstate',functi ...

  6. 给用户root权限

    1.添加用户,首先用adduser命令添加一个普通用户,命令如下: #adduser tommy //添加一个名为tommy的用户#passwd tommy   #passwd tommy //修改密 ...

  7. 批量判断网页是否NOT found

    import java.net.HttpURLConnection;import java.net.URL; public class NetValible{ static String[] url ...

  8. Linux实战教学笔记19:Linux相关网络知识梳理

    第十九节 Linux相关网络知识梳理 标签(空格分隔): Linux实战教学笔记-陈思齐 一,前言 一个运维有时也要和网络打交道,所以具备最基本的网络知识,对一个运维人员来说是必要的.但,对于我们的工 ...

  9. Linux下Mysql数据库互为主从的配置过程

    配置准备: 两台机器:A(193.168.10.101)  B(193.168.10.102) mysql大版本需要一致,小版本可忽略 配置过程: A(193.168.10.101) 机器配置: 执行 ...

  10. 【BZOJ 3261】最大异或和【可持久化字典树】

    题意 给出一个长度为n的整数序列,给出m个操作.操作有两种.1,Ax表示在序列结尾增加x.2,Qlrx表示找到一个位置p满足 l<=p<=r,使得a[p] xor a[p+1]xor... ...