通常来说查询的顺序呢~从 From -> Where -> Group By -> Select -> Order By
一般来说我们一个语句从查询开始,借助了 AdventureWorks2014 来举例
SELECT TOP 50 a.PersonType,a.LastName,a.FirstName,c.CardNumber,c.CardType FROM Person.Person a INNER JOIN Sales.PersonCreditCard b ON a.BusinessEntityID = b.BusinessEntityID INNER JOIN Sales.CreditCard c ON b.CreditCardID = c.CreditCardID ORDER BY a.BusinessEntityID
1、首先,执行这个查询,第一步首先会找到 From
在From 里面,决定标识那些需要查询和返回的表。如果说From 里面还有表运算符 (比如join) ,那还需要从左到右去执行处理这些运算符。每次运算,都是将1个或者2个表进行运算输入,返回一个输出表。返回的输出表作为再右边的表的左输入。以此类推。
最终的操作将为下一个操作作为输入表。
而每次的运算操作,都分为3个步骤
1、1 第一步会将左右2个表做个连接 ~比方说 a (m 行) 和 b(n行) 做了连接,那首先就会先做出一个 m*n 的虚拟表出来,标识着这2个表参与了连接操作
1、2 第二步会使用 on 来进行根据连接条件进行行筛选 ~ 这个就好理解罗~就是把连接条件是符合的挑选出来嘛~ 不过这里注意null 值的判断就可以
1、3 第三步是添加外部行,这个步骤是将保留表中被过滤的行重新添加进去虚拟表。
(*保留表 :我简单理解就是 a left join b 则 a 为保留表, a right join b 则b 为保留表 a full join b 则 ab 同为保留表)
2、 从from 里面标识了哪些行需要被检索出来之后,到了第二步 where 筛选。
(where的作用大家都知道了~我就不说了)
从where 进行筛选,和通过第一步的筛选有什么不一样呢? 不一样的地方在于。被 on 刷走的数据,有可能会通过添加外部行的时候从新添加到中间结果里面,但是如果被where 刷走的行,则是没有机会翻身了。这个是它们之间最大的区别
还有就是,通过where 的筛选器的时候在select 之前,所以在where 的筛选里面,不能使用列别名进行筛选。就是因为这是执行顺序所决定的
3、 group by 和 having
group by 也容易,就是将跟在 group by 之后的相同的 expression 值相同的,汇聚成一行进行显示。
having 嘛~就是对group by 之后聚合的结果可以使用having 进行一个筛选。
因为 group by 和 having 也都是在 select 之前,所以并不能使用列别名,只能用表达式
4、select
通过select 来查出返回到用户界面的实际数据到底是哪些列,哪些值
4、1 首先是需要计算表达式,在select 里面,是不允许有这种 select a+1 as b ,b+1 as c 即不允许应用列别名。
(*根据解释,因为sql server 的运算是并行的,所以在查询表达式的时候 a+1 和 b+1 是同时进行的,b+1 在运算的时候是不会知道别名b 是什么值,而是直接抛错)
4、2 根据步骤4.1 计算出来的表达式,然后就取用 distinct 关键字去重~ distinct 是在这一步才发挥作用哦~
4、3 最后是根据top 关键字决定是否全部返回结果集
5、Order by
Order By 是走到最后一步了~last shot
最后一步是通过 order by 决定返回的顺序。这个时候因为order by 在select 之后,所以order by 就可以引用列别名,但是也再不能使用 别名之前的表达式了(除非表达式是一个字段并且存在在表里面)
**关键点是通过order by 返回的数据,不是集合,是游标,是游标,是游标!!!这就是为什么在子查询,CTE等语句里面,不允许在不使用top 的情况下使用 order by ,就是因为order by 改变了集合而成为了游标!
好~说完了,说得不好的地方请用力拍
参考:<SQL Server 技术内幕:T-Sql 查询>