select语句的执行顺序
愤怒的菜鸟一只。
上星期受TODO的老师马伦影响,决定来博客园,结果拖到昨天开户。今天受百度开发者大会刺激,决定不拖拉了,一回家就开始提笔。
天啊,TODO今天才知道原来现在的建筑工在几百年前的中世纪也是很受人尊敬,很有社会地位,很赚钱的一个职业。为什么今天会变成这样的一个苦逼职业呢?因为当时的建筑工都必须懂建筑学,数学,几何等等,出了亲自动手施工以外必须自己设计;而现在,设计师独立出来了,普通的建筑工不必动脑子,只能动手,所以如此。IT建筑工什么的,TODO才不要当呢。
闲话扯完,今天先拿MSSQLServer里的最简单的T_SQL语句练练手。请大家有钱的捧个钱场,没钱的找人借钱捧个钱场,O(∩_∩)O谢谢。
注册时,TODO的申请博客原因填写如下:
select [Rmb_MM] as CAUSE_LOVE
from [itcast] as i,[baidu] as b ,[google] as g
where
b.国际知名度 = g.国际知名度 and
b.国内推荐度 = i.国内推荐度
group by [Rmb_MM]
having count([Rmb_MM]) > 10kAnd84.8cm_59.2cm_86.4cm
order by CAUSE_LOVE
top 10
那么,问题就来了,马伦老湿:“select语句的执行顺序是如何的?先执行select还是别的?”
TODO:我靠,你都说到这个份上了,那就肯定不是首先执行select。
确实,上百度去搜索数据,是一开始我们就知道数据的吗?
不是,是百度先在内部把数据处理后,再告诉外界,我们才知道的。
即是,别人先要告诉我们,我们才能知道;而不是我们先知道了,别人再告诉我们。
所以,T_SQL语句从from执行,经过一系列匹配,才开始select,然后是order by,最后top。这就解释了为什么在“select [Rmb_MM] as CAUSE_LOVE ”当中取得别名CAUSE_LOVE 只能在order by当中使用。因为在这之前执行其他步骤根本就没有创建该别名。事实上,order by也几乎是唯一一个能够应用select语句当中的别名的步骤。
详细点说,以上T_SQL语句执行顺序如下:
- from [itcast] as i,[baidu] as b ,[google] as g
- where b.国际知名度 = g.国际知名度 and b.国内推荐度 = i.国内推荐度
- group by [Rmb_MM]
- having count([Rmb_MM]) > 10kAnd84.8cm_59.2cm_86.4cm
- select [Rmb_MM] as CAUSE_LOVE
- order by CAUSE_LOVE
- top 10
第一步,会把表itcast(m行数据)与表baidu(n行数据)这两张表取出进行笛卡尔交叉连接,得到一个虚拟表V1(m*n行数据)。这一步骤一次只会取出最多两个表的数据。如果有更加多的表,比如此处的表google,会放到下一轮。如果有外表连接outer join(left join|right join|full join),那么会给相应的左表或者右表打上一个标记,留给第三步用。
第二步,会把以上得到的V1进行join_condition判断,只有令表连接条件(b.国际知名度 = g.国际知名度)为true的行才能得到保留,其他的行,全部米西米西。此处得到虚拟表V2。
第三步,外连接,如果左表或者右表被打上了标记,那么把在第二步被移除的行添加回来。此处得到V3(该实例没有,请各位自行脑补吧)。然后,如果有更多的表,比如此处的表google,那么把V3当做第一张表,google作为第二张表,开始重复前三步。直到全部的表处理完毕。
这就是为什么一般情况下TODO能用表连接就不用子查询——一种方式在前三步就全部完成,另一种方式必须把所有步骤都走一遍,前者自然比后者快。
同样也是为什么在大型项目中不能够直接首步使用表连接——假设数据库有两张100w条数据的table,100w*100w得死。如果TODO没有首先经过筛选,那么将来老板会炒TODO的鱿鱼。
第四步,会把以上最后得到的虚拟表进行where_condition筛选,只有令where筛选条件(比如:where salary>¥5000)为true的行才能得到保留,其他的行,死啦死啦的干活。然后的到V4.(该实例没有,同上)
接下来大家就熟悉了,第五步按照Rmb_MM字段分组,第六步使用having_conditiom筛选器,只有满足条件(聚合函数count([Rmb_MM]) > 10kAnd84.8cm_59.2cm_86.4cm )的才能保留。最后得到虚拟表V6。
第七步才开始处理我们熟悉的select语句,由此开始才能够使用其中所取的字段别名CAUSE_LOVE 。事实上这似乎也只能在下一步order by当中使用,或者子查询的外层。因为那个时候才创建好了CAUSE_LOVE,在此之前都是原生的Rmb_MM,这直接导致TODO只能在外行面前装一下了(~ o ~)Y,在内行面前是装不了的(>_<)。
OK,第一只愤怒的菜鸟发射完毕,也不知道效果怎么样。其实有时候很想写自己的从零开始的学习经历,但是回头一想,好像有没有什么可以写的。都是平平淡淡的,都是别人再网上发表过的,好像自己也没什么独到的,说不定这一篇已经好多人写过了。不过再想一想,反正那么多人写过了,少TODO一个不少,多TODO一个也不多,干嘛不拿过见证TODO的成长史呢?如果现在的TODO能够在这里写下“2年以后一定要具备访问外国技术论坛毫无压力的能力”,将来的TODO能够再次回来敲上“I’ve failed over and over again in my life, and that is why I succeed.”,那一定是这辈子TODO最帅的一刻。
希望自己多坚持写博客,希望大家多拍砖。希望能够给人带来帮助。

浙公网安备 33010602011771号