每个子句执行的次序已经在前面进行了标记,在一一介绍这些子句之前,我们要先明白,执行这个命令的输入是这些表名、条件(ON、WHERE和HAVING)以及一些字段名(SELECT,DISTINCT、ORDER BY、GROUP BY),其中表名标识的是物理存储的表,字段名是每一个表的字段的名称,条件是针对字段的或者该字段上执行的聚集函数的值得逻辑表达式。这些子句的每一步都是产生一个逻辑关系表。 1)、FROM操作,这一步的输入是多个表,在这一步是对多个关系表执行笛卡尔积操作,生成的结果是VT1,假设有3个表,t1、t2和t3,三个表分别有r1、r2、r3行,每个表有c1、c2、c3个字段,那么执行笛卡尔积得到的VT1则有r1*r2*r3行,有c1+c2+c3个字段。 2)、这一步是在第一步生成的VT的基础之上执行的判断操作,ON后面的逻辑表达式是一个针对VT1表上的每一行的判断,我们将淘汰不满足ON条件的行,但是一般情况下,我们执行逻辑操作返回的结果总是TRUE或者FALSE,但是在SQL中,可能存在第三个值,那就是NULL,这个一般被认为空(注意,不是空字符串),它既不是TRUE也不是FALSE,我们来看: mysql> select NULL = NULL \G *************************** 1. row *************************** NULL = NULL: NULL
mysql> select 0 = NULL \G *************************** 1. row *************************** 0 = NULL: NULL
mysql> select 1 = NULL \G *************************** 1. row *************************** 1 = NULL: NULL
mysql> select NULL != NULL \G *************************** 1. row *************************** NULL != NULL: NULL
所以,我们可以把NULL视为未知状态,所以两个未知状态也不是相等的。但是在条件判断的时候,我们要分出TRUE或者FALSE,因为我们要根据这个结果判断是否淘汰这一行,在ON子句中,是将NULL视为FALSE的,所以如果某一行的该字段是NULL,那么它将会被淘汰。例如:

<??http://www.2cto.com/kf/ware/vc/" target="_blank" class="keylink">vcD4KvdPXxaOsztLDx7+00rvPwr2r1eLSu7j2se3WtNDQzeq10b+otvu7/dauuvPU2da00NBPTrLZ1/e1w7W9tcS94bn7o7oKPGJyPgo8cD48L3A+CjxwPjxpbWcgc3JjPQ=="https://www.cppentry.com/upload_files/article/57/1_yrdfp__.png" alt="\">
可以从上例中看到,在笛卡尔积计算之后,一共产生了9行,然后执行ON操作,只剩下了3行满足条件的,而条件是t2.b!="hello',这就导致了t2表中只剩下了b='hello'的那一行,如上上一个图所示,但是如果执行了右外连接的操作,那么需要添加t2表(因为t2是连接操作右边的那个表)中缺失的每一行(这里需要添加两行),对于这两行除了t2字段外的其他字段,都补充NULL就可以了。如果将 上例中的t1和t2换一下,然后再讲right join换成left join,可以得到类似的结果,只不过补充的NULL出现在是右边。 4)、这一步执行的是我们最熟悉的WHERE子句,这一步是在VT3的基础上执行条件过滤,同样,只保留条件计算得到TRUE的行,淘汰结果为FALSE和NULL的行。将返回的结果标记为VT4。
ERROR 1111 (HY000): Invalid use of group function 2、由于在执行WHERE的时候并没有执行到SELECT操作,所以在SELECT操作中出现的as别名将不能用在WHERE子句中。 mysql> select t1.a as A from T1 as t1 right join T1 as t2 on t2.b != 'hello' A != 10; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'A != 10' at line 1 3、要明确WHERE是在添加缺失行之后执行的,而ON执行在添加缺失行之前,所以如果在ON和WHERE使用相同的逻辑计算,得到的结果可能不是相同的。 5)、这一步执行的是分组的操作,在VT4的基础上,根据GROUP BY确定的列进行分组,在GROUP BY子句中会认为所有的NULL都是相同的,而不是NULL != NULL,将它们分在一组,例如:
6)、with子句分为ROLLUP和CUBE两种,这两种我们基本上用不到,CUBE在mysql也不支持,ROLLUP只是在得到的结果添加额外的一行。
这里不探讨ROLLUP的作用了,假设它生成的结果为VT6 7)、执行HAVING子句,这个子句的作用也是将汇聚之后的每一组(在GROUP BY指定的列上相同的行为一组)进行判断,这是有区别与ON和WHERE子句的,它们都是对于上一个操作结果中的每一行进行判断,而HAVING是对每一组。这里可以是对一个或者多个字段的判断,也可以是每一个组中执行汇聚函数的判断。生成的结果是VT7。 但是,在HAVING执行的时候需要注意,虽然在GROUP BY的时候将执行列为NULL的划分到同一组了,但是对于某一列为NULL的时候,执行这一列的count操作会被认为为0的,例如:
但是在计算c