你真的懂T-sql吗?
你真的懂T-sql 语句的逻辑执行顺序吗?
先创建示例数据库
创建两个表 Class和Choose表,
class:
choose:
大家可能很容易看懂以下代码
目的是找出所有班级中学生人数少于3的班级和班级人数,
查出的结果
那它们的执行顺序和过程是怎么样的?分析一下
1.执行from语句中的两个表 ,执行笛卡尔乘积(交叉连接)
会得到虚拟表 VT1 ,表中会出现28条数据(4*7)。
2. on 筛选器(联接条件)
sql中的筛选器有三种(on,where,having),on 筛选器被应用到上步生成的虚拟表 VT1中的所有行。只有在 联接条件为 TRUE(满足ON条件)的时候才会包含在由步骤2产生的虚拟表VT2中,在此示例中 a.classname=b.classname,由此可以从虚拟表VT1中28条数据中筛选出6条数据
对于NULL值,在筛选器中(on,where,having)中,比较两个NULL值,结果为UNKNOWN(三值逻辑之一),会当做FALSE处理,然而在排序操作和分组操作等等,会认为NULL和NULL是相等的。
3.添加外部行
执行left outer join , 两表联接,如果left outer join,则左边为保留表,如果right outer join ,则右边为保留表,如果full outer join ,则两边都为保留表。
此步骤会返回VT2中的所有行以及保留表中在步骤2中过滤掉的行(外部行),外部行中非保留表中的列值赋为NULL,最后生成虚拟表VT3。
假如还有一张联表Student,那么就要重复1,2,3步了。
4.where 筛选器
选取 辅导员是 Michael 的行,返回虚拟表VT4。(此处未排序,不可用聚合筛选器)
5. 分组
返回虚拟表VT5,表中包括两个部分,Groups 和 Raw,即实际组构成的成组部分和由上一步返回的行组成的原始部分。
返回虚拟表VT5
这时候,因为不是筛选器,所以NULL与NULL认为是相等的。
六:CUBE或ROLLUP选项。
此示例没有,如有返回虚拟表 VT6
七:having 筛选器
筛选掉包含3名学生的班级,返回虚拟表VT7
八:处理select列表
返回虚拟表VT8 .
在select列表中创建的别名不能在前面的步骤中使用,而且不能在用于select表达式的其他表达式,受SQL的独有的特性--同时操作。
即:select a1+1 as b1,b1+1 as b2,这样是不支持的,因为它们是同时的,与逻辑顺序无关,在csharp交换值要用到临时变量,而T-sql不需要,直接update dbo.test set c1=c2,c2=c1 ,如此就交换了值,此操作是同时的,瞬间的。
select中创建的列的别名可以再order by中调用。
九:distinct子句
此示例没有,如果有则返回VT9。
十:order by子句
order by 认为两个NULL值相等,在T-sql中NULL排位比已知值低。
返回的是游标VC10 .并不是一个表。
会出现错误
十一:TOP
返回指定的行数或百分数。
令附一逻辑趣味题:
假设你被诊断得了一种怪病。医生给你开了两种药--A和B。每个瓶子装三个药片,两种药片的大小、形状、味道、颜色都一样。瓶子上有药的名称,一个瓶子盛A,另一个盛B,但药片本身没有任何标记。医生吩咐你每天吃一片A和一片B,共三天。正确服用,治愈你的病,否则,死亡。
第一天,你服了一片A和一片B,第二天,你发现有人动了你的药,瓶子B空了,瓶子A里有一个药片,餐桌上放着三个药片。你意识到药片已经混了。你打电话给药房得知今天没货。
你该怎样正确服药呢?