SQL 执行顺序

⑨ SELECT ⑩ DISTINCT column,
⑥ AGG_FUNC(column or expression), ...
① FROM left_table
		③ JOIN right_table
		② ON tablename.column = other_tablename.column
④ WHERE constraint_expression
⑤ GROUP BY column
⑦ WITH CUBE|ROLLUP
⑧ HAVING constraint_expression
⑪ ORDER BY column ASC|DESC
⑫ LIMIT count OFFSET count;

FROM:笛卡尔积。

ON:主表保留。

JOIN:不符合 \(on\) 也添加。

WHERE:非聚合、非 \(select\) 别名。

GROUP BY:改变表的引用。

AGG_FUNC:聚合计算。

WITH\(cube\)\(rollup\)

HAVING:只作用分组后。

SELECT:选择列、表达式计算。

DISTINCT:行去重。

ORDER BY:排序。

LIMIT:选择指定数量行、数量列。

\(SQL\) 的执行顺序发现,所有查询语句都是从 \(from\) 开始。在执行过程中,每个步骤都会为下一个步骤生成一个虚拟表,这个虚拟表将作为下一个执行步骤的输入。


1. from 执行笛卡尔积

\(from\)\(SQL\) 语句执行的第一步。对 \(from\) 子句中的表计算笛卡尔积(交叉联接),生成虚拟表 \(t1\),获取不同数据源的数据集。

\(from\) 子句执行顺序为从后到前,从左到右,\(from\) 子句中写在最后的表(基础表 \(driving\ table\))将被最先处理,即最后的表为驱动表,当 \(from\) 子句中包含多个表的情况下,需要选择数据最少的表作为基础表


2. on 筛选器

对虚拟表 \(t1\) 应用 \(on\) 筛选器,\(on\) 中的逻辑表达式将应用到虚拟表 \(t1\) 中各个行,筛选出满足 \(on\) 逻辑表达式的行,生成虚拟表 \(t2\)


3. join 添加外部行

如果指定了 \(outer\ join\) 保留表中未找到匹配的行将作为外部行添加到虚拟表 \(t2\),生成虚拟表 \(t3\)。保留表如下:

  • \(left\ outer\ join\):把左表记为保留表。
  • \(right\ outer\ join\):把右表记为保留表。
  • \(full\ outer\ join\):把左右表都作为保留表。

在虚拟表 \(t2\) 的基础上添加保留表中被过滤条件过滤掉的数据,非保留表中的数据被赋予 \(NULL\) 值,最后生成虚拟表 \(t3\)

如果 \(from\) 子句中包含两个以上的表,则对上一个联接生成的结果和下一个表重复执行步骤 \(1\)~\(3\),直到处理完所有表为止。


4. where 筛选器

对虚拟表 \(t3\) 应用 \(where\) 筛选器。根据指定条件对数据进行筛选,并把满足的数据插入虚拟表 \(t4\)

  • 由于数据还没分组,所以还不能在 \(where\) 过滤器中使用聚合函数对分组统计的过滤。
  • 由于还没进行列的选取操作,因此在 \(select\) 中使用列的别名也是不允许的。

5. group by 分组

\(group\ by\) 子句中的列/列表将虚拟表 \(t4\) 中的行唯一的值组合成一组,生成虚拟表 \(t5\)。如果应用了 \(group\ by\),那么后面的所有步骤都只能得到虚拟表 \(t5\) 的列或聚合函数(\(count、sum、avg\) 等)。原因在于最终的结果集中只为每个组包含一行。

同时,从这一步开始,后面的语句中都可以使用SELECT中的别名。


6. agg_func 计算聚合函数

常用聚合函数:\(avg、count、first、last、max、min、sum\)


7. with 应用 rollup或cube

对虚拟表 \(t5\) 应用 \(rollup\)\(cube\) 选项,生成虚拟表 \(t6\)

\(cube\)\(rollup\) 区别:

  • \(cube\) 生成的结果数据集显示了所选列中值的所有组合的聚合。
  • \(rollup\) 生成的结果数据集显示了所选列中值的某一层次结构的聚合。

8. having 筛选器

对虚拟表 \(t6\) 应用 \(having\) 筛选器。根据指定条件对数据进行筛选,并把满足的数据插入虚拟表 \(t7\)

\(having\) 语句在 \(SQL\) 中的主要作用与 \(where\) 语句相同。但 \(having\) 是过滤聚合值,在 \(SQL\)增加 \(having\) 子句原因就是,\(where\) 关键字无法与聚合函数一起使用,\(having\) 子句主要和 \(group\ by\) 子句配合使用。


9. select 选出指定列

将虚拟表 \(t7\) 中的 \(select\) 中出现的列筛选出来,并对字段进行处理,计算 \(select\) 句中的表达式,产生表 \(t8\)


10. distinct 行去重

将重复的行从虚拟表 \(t8\) 中移除,产生虚拟表 \(t9\)\(distinct\) 用来删除重复行,只保留唯一的。


11. order by 排列

将虚拟表 \(t9\) 中的行按 \(order\ by\) 子句中的列/列表排序,生成游标 \(t10\),注意不是虚拟表。因此使用 \(order\ by\) 子句查询不能应用于表达式。同时,\(order\ by\) 子句的执行顺序为从左到右排序,是非常消耗资源的。


12. limit/offset 指定返回行

\(t10\) 的开始处,选择指定数量行,生成虚拟表 \(t11\),并返回调用者。



posted @ 2022-05-16 19:34  做梦当财神  阅读(99)  评论(0编辑  收藏  举报