SQL语句执行顺序结合上图,整理出以下伪SQL查询语句。从这个序列我们可以发现,所有的查询语句都是从FROM开始执行的。在实际执行过程中,每一步都会为下一步生成一个虚拟表,这个虚拟表将作为下一个执行步骤的输入。下面详细介绍每一步的具体执行过程。1FROMCartesianProductFROM是SQL语句执行的第一步,不是SELECT。FROM子句中对前两张表进行笛卡尔积(crossjoin),生成虚拟表VT1,从不同数据源获取数据集。FROM子句的执行顺序是从后到前,从右到左。FROM子句中写入的最后一张表(基本表驱动表)会被优先处理,即最后一张表为驱动表。当FROM子句是多表的情况下,我们需要选择数据最少的表作为基表。2ONApplytheONfiltertothevirtualtableVT1将ONfilter应用于虚拟表VT1。ON中的逻辑表达式将应用于虚拟表VT1中的每一行,过滤掉满足ON逻辑表达式的行,生成虚拟表VT2。3JOIN添加外部行如果指定了OUTERJOIN,则在保留表中找不到匹配的行将作为外部行添加到虚拟表VT2中,并生成虚拟表VT3。保留表如下:LEFTOUTERJOIN将左表标记为保留表RIGHTOUTERJOIN将右表标记为保留表FULLOUTERJOIN将左右表都作为保留表,并根据虚拟表VT2通过过滤条件过滤掉丢失的数据,非保留表中的数据被赋予NULL值,最终生成虚拟表VT3。如果FROM子句包含两个以上的表,则对上一个join生成的结果表和下一个表重复步骤1-3,直到处理完所有表。4WHEREApplytheWEHREfilter将WHERE过滤器应用于虚拟表VT3。按照指定的条件过滤数据,将满足的数据插入到虚拟表VT4中。由于数据还没有分组,所以还不能在WHERE过滤器中使用聚合函数来过滤分组统计。同时,由于还没有进行列选择操作,所以在SELECT中也不允许使用列别名。5GROUPBY根据GROUPBY子句中的列/列表,将虚拟表VT4中行的唯一值分组为一组,生成虚拟表VT5。如果应用GROUPBY,那么后面的所有步骤只能得到虚拟表VT5的列或聚合函数(count、sum、avg等)。原因是最终结果集每组只包含一行。同时,从这一步开始,SELECT中的别名就可以在后面的语句中使用了。6AGG_FUNC计算聚合函数计算max等聚合函数。SQL聚合函数计算从列中获得的值,返回单个值。常用的聚合函数包括以下几种:AVG:返回平均值COUNT:返回行数FIRST:返回第一条记录的值LAST:返回最后一条记录的值MAX:返回最大值MIN:返回最小值SUM:返回和7WITHApplyROLLUPorCUBEApplyROLLUPorCUBEoptiontovirtualtableVT5togeneratevirtualtableVT6.CUBE和ROLLUP的区别如下:CUBE产生一个结果数据集,显示所选列中所有值组合的聚合。ROLLUP生成的结果数据集显示了所选列中值的一些层次聚合。8HAVING应用HAVING过滤器将HAVING过滤器应用于虚拟表VT6。按照指定的条件过滤数据,将满足的数据插入到虚拟表VT7中。SQL中HAVING语句的主要作用与WHERE语句相同,只是HAVING是对聚合值进行过滤。在SQL中加入HAVING子句的原因是WHERE关键字不能与聚合函数一起使用。HAVING子句主要与GROUPBY相关,与子句结合使用。9SELECT在虚拟表VT7中选择指定列过滤掉SELECT中出现的列,并对字段进行处理,计算SELECT子句中的表达式,生成虚拟表VT8。10DISTINCTdeduplicatestherepeatedrowsRemovefromvirtualtableVT8生成虚拟表VT9。DISTINCT用于删除重复行,只保留唯一行。11ORDERBY排列根据ORDERBY子句中的列/列表对虚拟表VT9中的行进行排序,生成游标VC10。请注意,它不是虚拟表。因此带有ORDERBY子句的查询不能应用于表达式。同时,ORDERBY子句的执行顺序是从左到右排序的,资源消耗很大。12LIMIT/OFFSET指定返回行从VC10开始选取指定行数,生成虚表VT11,返回给调用者。示例接下来,让我们看一个示例。下面的SQL查询语句有没有问题?首先我们看一下上面SQL的执行顺序,如下:首先执行FROM子句,从学生成绩表中组装数据源的数据。执行WHERE子句,过滤学生成绩表中所有学生的数学成绩不为NULL的数据。执行GROUPBY子句以按“班级”字段对学生成绩表进行分组。计算avg聚合函数,通过找到每个班级组,求出数学的平均成绩。执行HAVING子句,过滤掉数学班级平均分大于75的。执行SELECT语句,返回数据,不过不用担心,后面的几步还需要执行。执行ORDERBY子句将最终结果按“数学平均”排序。执行LIMIT,限制返回3条数据。结合ORDERBY子句,它返回前三个类及其在所有类中的数学平均值。想一想,如果我们把上面的语句改成下面这样呢?我们发现如果把avg(数学成绩)>75放在WHERE子句中,此时GROUPBY语句还没有执行,所以此时聚合值avg(数学成绩)还是未知的,所以会报错被举报。
