1.3.4.10 SELECT的执行顺序

曾在1.3.4.5 日期运算 小节中,遇到别名出现在不同的字句中的情形,出现在 where 字句中,无法执行,直接报错。而出现在 order by 字句中,可以正常执行,这个和 SELECT 的执行顺序有关。

SELECT语句的完整语法:

(7)  SELECT 
(8)  DISTINCT [select_list]
(1)  FROM [left_table]
(3)  [join_type] JOIN [right_table]
(2)  ON [join_condition]
(4)  WHERE [where_condition]
(5)  GROUP BY [group_by_list]
(6)  HAVING [having_condition]
(9)  ORDER BY [order_by_condition]
(10) LIMIT [limit_number]

语法前面的序号为SELECT执行顺序;

MySQL的SELECT执行顺序一共分为10步,如上所标注的那样,最先执行的是FROM操作,最后执行的是LIMIT操作。其中每一次操作都会产生一张虚拟的表,这个虚拟的表作为一个处理的输入,只是这些虚拟的表对用户来说是透明的,但是只有最后一个虚拟的表才会被作为结果返回。如果没有在语句中指定某一个子句,那么将会跳过相应的步骤。

下面我们来具体分析一下查询处理的每一个阶段:

 SELECT a.customer_id, COUNT(b.order_id) as total_orders
 FROM table1 AS a
 LEFT JOIN table2 AS b
 ON a.customer_id = b.customer_id
 WHERE a.city = 'hangzhou'
 GROUP BY a.customer_id
 HAVING count(b.order_id) < 2
 ORDER BY total_orders DESC
 LIMIT 0, 10;
  1. FORM: 对 FROM 左边的表和右边的表计算笛卡尔积,产生虚表 VT1
  2. ON: 对虚表 VT1 进行 ON 过滤,只有那些符合 <join-condition> 的行才会被记录在虚表 VT2 中。
  3. JOIN: 如果指定了 OUTER JOIN(比如left join、 right join),那么保留表中未匹配的行就会作为外部行添加到虚拟表 VT2 中,产生虚拟表 VT3
  4. WHERE: 对虚拟表 VT3 进行 WHERE 条件过滤。只有符合 <where-condition> 的记录才会被插入到虚拟表 VT4 中。
  5. GROUP BY: 根据 group by 子句中的列,对 VT4 中的记录进行分组操作,产生 VT5
  6. HAVING: 对虚拟表 VT5 应用 having 过滤,只有符合 <having-condition> 的记录才会被 插入到虚拟表 VT6 中。
  7. SELECT: 执行 select 操作,选择指定的列,插入到虚拟表 VT7 中。
  8. DISTINCT: 对 VT7 中的记录进行去重。产生虚拟表 VT8.
  9. ORDER BY: 将虚拟表 VT8 中的记录按照 <order_by_list> 进行排序操作,产生虚拟表 VT9.
  10. LIMIT:取出指定行的记录,产生虚拟表 VT10, 并将结果返回。

了解到上面的内容,我们就可以很清楚的知道,为什么别名 monthBirth 出现在 where 字句中会报错,因为 monthBirth 出现在第 7 步中,而 where 在第 4 步中就执行了,所以错误消息提示:ERROR 1054 (42S22): Unknown column 'monthBirth' in 'where clause' ,而 order by 在 select 之后执行。

results matching ""

    No results matching ""