sqlserver2005T-SQL查询语句的逻辑查询处理1

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现在看来已经很老了,但是读起这本书还是能够获得很多有用的知识。上面就是,因此

决定对于这一系列的书好好读一读,吸取些养分。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值