SQL ,T-SQL
1.逻辑查询处理的顺序
 
(8)select  (9)distinct (11)<top_specifincation> <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)from : 对from子句中的前两个表执行笛卡尔积(交叉连接),生成虚拟表VT1. 

 
(2) on:  对于VT1应用on筛选器。只有那些使用 <join_condition>为真的行才被插入VT2。 

 
(3) outer(join): 如果指定了outerjoin(与cross join 或inner join不同),保留表中未 

 
找到匹配的行将作为外部行添加到VT2,生成VT3.如果from子句包含两个以上的表,则对上一个 

 
连接生成的结果表和下一个表重复执行步骤1到步骤3,指导处理完所有的表为止。 

 
(4)  where : 对于VT3应用where筛选器。只有<where_condition>为true的行才被插入VT4。 

 
(5) group  by :按group by子句中的列列表对于VT4进行分组,生成VT5。 

 
(6) cube | rollup  把超组插入VT5,生成VT6。 

 
(7)having 对VT6应用having 筛选器。只有使用<having_condition>为true的组才会被插入VT7。 

 
(8)select :处理select列表,生成VT8。 

 
(9) distinct :将重复行从VT8中删除,产生VT9。 

 
(10) order by :将VT9的行按照ORDER BY子句的列列表排序,生成一个游标(vc10) 

 
(11)top :从vc10的开始出选择指定数量或比例的行,生成VT11,并返回给调用者。 

 
 

set nocount on;
 use tempdb; 

 go 



 if object_id('dbo.Orders') is not null 

  drop table dbo.Orders; 

 go 

 if object_id('dbo.Customers') is not null 

drop table dbo.Customers; 

 go 



 create table dbo.Customers( 

 customerid char(5) not null primary key, 

 city varchar(10) not null 

 ); 

 insert into dbo.Customers(customerid,city)values('FISSA','Madrid'); 

 insert into dbo.Customers(customerid,city)values('FRNDO','Madrid'); 

 insert into dbo.Customers(customerid,city)values('KRLOS','Madrid'); 

 insert into dbo.Customers(customerid,city)values('MRPHS','Zion'); 



 create table dbo.Orders( 

 orderid int not null primary key, 

 customerid char(5) null references Customers(customerid) 

 ); 



 insert into dbo.Orders(orderid,customerid)values(1,'FRNDO'); 

 insert into dbo.Orders(orderid,customerid)values(2,'FRNDO'); 

 insert into dbo.Orders(orderid,customerid)values(3,'KRLOS'); 

 insert into dbo.Orders(orderid,customerid)values(4,'KRLOS'); 

 insert into dbo.Orders(orderid,customerid)values(5,'KRLOS'); 

 insert into dbo.Orders(orderid,customerid)values(6,'MRPHS'); 

 insert into dbo.Orders(orderid,customerid)values(7,null); 



 --查询订单数来自Madrid且订单数少于3(包括0个订单)的消费者,并包含他们的订单数。 

 --查询结果按订单数排序,从小到大。 

 select * from Customers; 

 select * from Orders; 



 select c.customerid ,count(o.orderid) ordernum 

 from Customers c left outer join Orders o  

 on c.customerid = o.customerid 

 where c.city ='Madrid' 

 group by c.customerid 

 having count(o.orderid)<3 

 order by ordernum  



 --这里涉及到三值逻辑,在sql中除了true、false,之外还有unknown,这三个逻辑。 

 --对于true 和false的逻辑我们都懂,但是对于unknown的逻辑对于筛选器 on where having  

 --则都是认为false处理的,如null和任何值比较都是unknown,筛选器中认为是false 

 --但是对于check约束检查时候则是认为是true处理,如插入一个null,但是约束null>4可以认为是正确的 

 select * from Customers where NULL=NULL 

 --上面的查询结果是空 

 但是对于unique约束、排序操作和分组操作则是认为两个NULL值是相等的。因此了解unknown的逻辑结果和null在不同 

 语言元素中被处理的方式是有好处的。 

 

 

 select * from Orders where customerid = null 

 select * from Orders where customerid is null  

 这两句的结果是有明显差异的,通过上面讲的三值逻辑问题,我们可以看出对于null值的判断=并不会产生效果,因为 

 null=null在筛选器中(on,where,having)中的结果是unknown的,也就是默认为false,因此并不会将结果返回的。 

 如果想要判断null,可以用is null或者是is not null来处理 



 2.为什么where筛选器中不能使用select中的别名? 

 因为参照语句逻辑执行的过程,where子句是第(4)步,而别名是执行到第(8)步之后的,从前后关系看是不可以使用的。 

 同时为什么where子句中不能使用分组函数等,也是这个道理,因为分组是在where之后执行的,当前虚拟表中没有分组的 

 内容和操作,因此也是不可以的。 



 3.聚合函数对于null是忽略的,同时子查询不能作为聚合函数的输入。 



 4 关于order by 和top的  

 --(下面的语句出错)除非另外还指定了 TOP 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效 

 select * from ( 

 select * from Orders order by orderid  

 ) 



 --正确的,       需要在表表达式后面的括号加一个表的别名,如dd,注意上面那个错误的原因提示 

 select * from ( 

 select top 5 * from Orders order by orderid 

) dd
这是在sqlserver2005技术内幕-T-SQL查询中所学的,虽然sqlserver2005现在看来已经很老了,但是读起这本书还是能够获得很多有用的知识。上面就是,因此
决定对于这一系列的书好好读一读,吸取些养分。