SQL执行顺序
结论
1. FROM <left_table>
2. ON<join_condition>
3. <join_type>JOIN<right_table>
4. WHERE<where_condition>
5. GROUP BY<group_by_list>
6. HAVING<having_condtion>
7. SELECT<Select_list>
8. DISTINCT<Select_list>
9. ORDER BY<order_by_list>
10.LIMIT<limit_number>
原表结构 & 数据
student 表数据
SELECT * FROM student;
teacher 表数据
SELECT * FROM teacher;
# 常规的输入顺序
SELECT t.Tid, t.name, AVG(s.Score)
FROM student s left join teacher t ON s.Sid=t.Sid
WHERE s.Score>60
GROUP BY t.Tid
HAVING AVG(s.score)>70
ORDER BY AVG(s.score);
LIMIT 0,1
# mysql 处理 SQL 的顺序
1) FROM student s
2) ON s.Sid=t.Sid
3) left join teacher t
4) WHERE s.Score>60
5) GROUP BY t.Tid
6) HAVING AVG(s.score)>60
7) SELECT t.Tid, t.name, AVG(s.Score)
# 8) DISTINCT<>
9) ORDER BY t.Tid;
10) LIMIT
步骤拆解
在这些SQL语句的执行过程中,几乎每一步都会产生一个虚拟表,用来保存SQL语句的执行结果(这是重点),我现在就来跟踪这个虚拟表的变化,得到最终的查询结果的过程,来分析整个SQL逻辑查询的执行顺序和过程。
FROM
对FROM子句中的前两个表(student & teacher)执行笛卡尔积(Cartesian product)。相当于如下SQL,得到VT1表。
SELECT * FROM student CROSS JOIN teacher;
ON
执行完笛卡尔积以后,接着就进行ON s.Tid = t.Tid条件过滤,根据ON中指定的条件,去掉那些不符合条件的数据,如下SQL语句,得到VT2表。
SELECT * FROM student s CROSS JOIN teacher t ON s.Tid=t.Tid;
JOIN
这一步只有在连接类型为OUTER JOIN时才发生,如LEFT OUTER JOIN、RIGHT OUTER JOIN和FULL OUTER JOIN。在大多数的时候,我们都是会省略掉OUTER关键字的,但OUTER表示的就是外部行的概念。相当于如下SQL,得到VT3表。
SELECT * FROM student s LEFT JOIN teacher t ON s.Tid=t.Tid;
WHERE
对VT3进行WHERE过滤,只有符合<where_condition>的记录才会输出到虚拟表VT4中。当我们执行WHERE s.Score>60 的时候,如下SQL语句,得到VT4表。
SELECT * FROM student s LEFT JOIN teacher t ON s.Tid=t.Tid WHERE s.Score>60;
GROUP BY
对VT4表进行分组操作。我们执行测试语句中的GROUP BY a.customer_id,相当如下SQL语句,得到VT5。
SELECT * FROM student s LEFT JOIN teacher t ON s.Tid=t.Tid WHERE s.Score>60 GROUP BY s.Tid;
HAVING
主要和GROUP BY子句配合使用,对分组得到的VT5虚拟表进行条件过滤。当我执行测试语句中的HAVING AVG(s.Score)>70 时,相当如下SQL,得到VT6。
SELECT * FROM student s LEFT JOIN teacher t ON s.Tid=t.Tid WHERE s.Score>60 GROUP BY s.Tid HAVING AVG(s.Score)>70;
SELECT
现在才会执行到SELECT子句,不要以为SELECT子句被写在第一行,就是第一个被执行的。
SELECT s.Tid, t.name, AVG(s.Score) FROM student s LEFT JOIN teacher t ON s.Tid=t.Tid WHERE s.Score>60 GROUP BY s.Tid HAVING AVG(s.Score)>70;