SQL执行顺序
1 | (8) SELECT (9) DISTINCT (11) <TOP_specification> <select_list> |
- FORM: 对 from 子句中的前两个表执行计算笛卡尔积,产生虚表 VT1。
- ON: 对虚表 VT1 进行
on
筛选,只有那些符合<join-condition>
的行才会被记录在虚表 VT2 中。 - JOIN: 如果指定了
outer join
, 那么这一步就将添加外部行。left outer jion
就把左表在第二步中过滤的添加进来,如果是right outer join
那么就将右表在第二步中过滤掉的行添加进来,这样生成虚拟表 vt3 。如果 from 子句中包含两个以上的表的话,那么就会对上一个 join 连接产生的结果 VT3 和下一个表重复执行步骤1~3这三个步骤,一直到处理完所有的表为止。 - WHERE: 对虚拟表 VT3 进行
where
条件过滤。只有符合<where-condition>
的记录才会被插入到虚拟表 VT4 中[注1]。 - GROUP BY: 根据
group by
子句中的列,对 VT4 中的记录进行分组操作,产生 VT5 。如果应用了group by
,那么后面的所有步骤都只能得到的 VT5 的列或者是聚合函数。 - CUBE | ROLLUP: 对表 VT5 进行
cube
或者rollup
操作,生成超组,产生表 VT6 。 - HAVING: 对虚拟表 VT6 应用
having
过滤,只有符合<having-condition>
的记录才会被 插入到虚拟表 VT7 中。having
筛选器是第一个也是为唯一一个应用到已分组数据的筛选器。 - SELECT: 执行
select
操作,选择指定的列,插入到虚拟表 VT8 中。 - DISTINCT:对 VT8 中的记录进行去重。产生虚拟表 VT9 。事实上,如果应用了
group by
子句那么distinct
是多余的,原因同样在于,分组的时候是将列中唯一的值分成一组,同时只为每一组返回一行记录,那么所以的记录都将是不相同的。 - ORDER BY: 将虚拟表 VT9 中的记录按照
<order_by_list>
进行排序操作,产生虚拟表 VT10 [注2]。 - LIMIT:取出指定行的记录,产生虚拟表 VT11 , 并将结果返回。
注
1. where 与 on区别
where
的过滤是最终的,on
是暂时的,如果在第二步被过滤掉,在第三步有机会找回来,但是 where
则不行。举个简单的例子,有一个学生表(班级,姓名)和一个成绩表(姓名,成绩),我现在需要返回一个x班级的全体同学的成绩,但是这个班级有几个学生缺考,也就是说在成绩表中没有记录。为了得到我们预期的结果我们就需要在 on 子句指定学生和成绩的关系(学生.姓名=成绩.姓名
),那么我们发现在执行第二步的时候,对于没有参加考试的学生记录就不会出现在 VT2 中,因为他们被 on
的逻辑表达式过滤掉了,但是我们用 left outer join
就可以把左表(学生表)中没有参加考试的学生找回来。如果在 on
中应用学生.班级='x'
的话,left outer join
会把x班级的所有学生记录找回,所以只能在 where
筛选器中应用学生.班级='x'
因为它的过滤是最终的。
2. order by
使用 order by
之后返回的一个游标,而不是虚拟表。sql是基于集合的理论的,集合不会预先对他的行排序,它只是成员的逻辑集合,成员的顺序是无关紧要的。对表进行排序的查询可以返回一个对象,这个对象包含特定的物理顺序的逻辑组织。这个对象就叫游标。正因为返回值是游标,那么使用 order by
子句查询不能应用于表表达式。排序是很需要成本的,除非你必须要排序,否则最好不要指定 order by
,最后,在这一步中是第一个也是唯一一个可以使用 select
列表中别名的步骤。