0%

SQL | SQL语句执行顺序

SQL语句执行顺序

graph TB;
    id0(FROM)-->id1(JOIN);
    id1-->id2(ON);
    id2-->id3(WHERE);
    id3-->id4(GROUP BY);
    id4-->id5(AVG,SUM,...);
    id5-->id6(HAVING);
    id6-->id7(SELECT);
    id7-->id8(DISTINCT);
    id8-->id9(ORDER BY);
  • 所有的查询语句都是从FROM开始执行的
  • 在执行过程中,每个步骤都会为下一个步骤生成一个虚拟表,该虚拟表将作为下一个执行步骤的输入
  1. 执行FROM子句,生成虚拟表vt1(选择相对小的表做基础表)
  2. 应用ON筛选器,ON中的逻辑表达式将应用到vt1中的各个行,筛选出符合条件的行,生成虚拟表vt2
  3. 执行JOIN语句,添加
  • 如果是OUTER JOIN,则添加外部行
  • 如果是LEFT OUTER JOIN,则添加左表在第二步中过滤后得到的行
  • 如果是RIGHT OUTER JOIN,则添加右表在第二步中过滤后得到的行

生成虚拟表vt3
4. 如果FROM子句中的表数目多于2个表,则将vt3和第三个表重复13的步骤,得到的虚拟表记为`vt3`;将`vt3`和第四个表重复13的步骤,得到的虚拟表记为vt3;……直到处理完FROM子句中的所有的表
5. 对虚拟表vt3应用WHERE筛选器,生成虚拟表vt4
6. GROUP BY col_name子句按col_name列聚合(col_name相同值为一组),得到虚拟vt5

  • 如果应用了GROUP BY,则后面的步骤都只能得到vt5表的列或使用关于vt5表的列的聚合函数(COUNT,SUM,AVG等)
  • GROUP BY将列中唯一的值分成一组,同时只为每一组返回一行记录
  1. Oracle特有:应用CUBEROLLUP选项,为vt5生成超组,得到虚拟表vt6
  2. 应用HAVING筛选器,生成虚拟表vt7
  • HAVING是第一个也是唯一一个应用到已分组数据的筛选器
  1. 处理SELECT子句,将虚拟表vt7中出现的列筛选出来,生成虚拟表vt8
  2. 应用DISTINCT子句,移除vt8中相同的行,生成虚拟表vt9
  • 如果应用了GROUP BY子句,则DISTINCT子句是多余的
  • GROUP BY的效率比DISTINCT
  1. 应用ORDER BY子句,返回一个游标,而不是虚拟表
  • 是第一个也是唯一一个可以使用SELECT列表中别名的步骤
  1. 应用TOP,将返回结果给请求者

以MySQL为例,写的SQL语句顺序为

1
2
3
4
5
6
7
SELECT ... 
FROM ... JOIN ... ON ...
WHERE ...
GROUP BY ...
HAVING ...
ORDER BY ...
LIMIT ... [OFFSET ...]

执行顺序

1
2
3
4
5
6
7
FROM ... JOIN ... ON ...
WHERE ...
GROUP BY ...
HAVING ...
SELECT ...
ORDER BY ...
LIMIT ... [OFFSET ...]

Oracle

Oracle中,在进行多列分组统计时,如果直接使用GROUP BY子句指定分组列,则只能生成基于所有分组列的统计结果。

如果在GROUP BY子句中使用ROLLUP语句或CUBE语句,除了生成基于所有指定列的分组统计外,还可以生成基于指定列不同子集的统计结果。

CUBE

使用CUBE选项,除了生成基于所有指定列的分组统计外,还对指定分组列的所有子集进行统计

1
GROUP BY CUBE(A,B,C)

形成的统计包括以下内容:

  • GROUP BY:不基于任何列的整个查询结果的统计
  • GROUP BY A:基于A列的分组统计
  • GROUP BY B:基于B列的分组统计
  • GROUP BY C:基于C列的分组统计
  • GROUP BY A,B:基于A、B两列的分组统计
  • GROUP BY A,C:基于A、C两列的分组统计
  • GROUP BY B,C:基于B、C两列的分组统计
  • GROUP BY A,B,C:基于A、B、C三列的分组统计

ROLLUP

使用ROLLUP选项,除了生成基于所有指定列的分组统计外,还对指定的分组列从左开始的每个子集进行统计。

1
GROUP BY ROLLUP(A,B,C)

形成的统计包括以下内容:

  • GROUP BY:不基于任何列的整个查询结果的统计
  • GROUP BY A:基于A列的分组统计
  • GROUP BY A,B:基于A、B两列的分组统计
  • GROUP BY A,B,C:基于A、B、C三列的分组统计

参考资料

Thank you for your approval.

欢迎关注我的其它发布渠道