sqlserver2005T-SQL查询语句的逻辑查询处理1
发布时间:2020-12-12 13:08:21 所属栏目:MsSql教程 来源:网络整理
导读: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
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',city)values('KRLOS',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,customerid)values(3,'KRLOS'); insert into dbo.Orders(orderid,customerid)values(4,customerid)values(5,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现在看来已经很老了,但是读起这本书还是能够获得很多有用的知识。上面就是,因此 决定对于这一系列的书好好读一读,吸取些养分。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |