CREATE TABLE t(
a CHAR(5)
)ENGINE=INNODB;
INSERT INTO t(a) VALUES(‘a’),(NULL),(‘b’),(‘c’),(NULL);
SELECT * FROM t ORDER BY a;
//这也是一个小技巧,当想使用GROUP BY后,想统计各个组/块的数量,可以使用COUNT(1)
SELECT a,COUNT(1) FROM t GROUP BY a;
结果如上,很清楚可以看到order by会把值为null的排在一起,而GROUP BY会把NULL的规划在同一块上,也就证明了NULL = NULL。
所以Mysql判断逻辑会有三种表达式,TRUE、FALSE、UNKNOWN(UNKNOWN是根据情况为TRUE或者为FALSE)。
因此在产生虚拟表VT2时,会增加一个额外的列来表示ON过滤条件的返回值,返回值有TRUE、FALSE、UNKNOWN,会取出比较值为TRUE的记录,然后产生虚拟表VT2。
3、添加外部行
这一步只有在连接类型为OUTER JOIN时才会发生(因为只有发生外联结匹配的时候),比如LEFT OUTER JOIN、RIGHT OUTER JOIN、FULL OUTER JOIN。在很多时候,我们可以将OUTER关键字省略掉,但OUTER其实代表的就是外部行,LEFT OUTER JOIN把左表记为保留表,RIGHT OUTER JOIN把右表记为保留表,而FULL OUTER JOIN就是把左右表都记为保留表。
添加外部行的工作就是在VT2表的基础上添加保留表中被过滤条件过滤掉的数据,非保留表中的数据被赋予NULL值,最后生成虚拟表VT3。
4、应用WHERE过滤器
对上一步骤产生的虚拟表VT3进行WHERE条件过滤,只有符合<where_condition>的记录才会输出到虚拟表VT4中。
在当前应用WHERE过滤器时,有两种过滤是不被允许的。
-
由于数据还没有分组,因此现在还不能在WHERE过滤器中使用<where_condition=MIN(col)>,这类对统计的过滤,这也是因为顺序问题,聚合函数,是要进行聚合分组操作才会出现的,也就是GROUP BY,WHERE的执行顺序在GROUP BY之前,所以会报错Invalid use of group function。
-
由于没有进行列的选取操作,因此在SELECT中使用列的别名也是不被允许的,比如SELECT city as c FROM t WHERE c = 'ShangHai’是不被允许出现的。这是因为取别名,是返回结果的时候才进行的,也就是起码要进行SELECT语句后,才进行SELECT语句后面的字段,也就是别名c最早能被识别,是处理SELECT后面列的时候,但此时执行WHERE并还没有执行SELECT,所以别名c是找不到的。
CREATE TABLE t4(
id INT PRIMARY KEY AUTO_INCREMENT,
city VARCHAR(255)
)ENGINE=INNODB,CHARSET=utf8
INSERT INTO t4(city) VALUES(“ShangHai”),(“BeiJing”),(“HongKong”);
SELECT city FROM t4 WHERE id = MIN(id);
CREATE TABLE t3(
city VARCHAR(100)
)ENGINE=INNODB,CHARSET=utf8;
INSERT INTO t3(city) VALUES(“ShangHai”),(“BeiJing”),(“HongKong”);
//下面语句无法执行,因为c此时还没存在
SELECT city AS c FROM t3 WHERE c = “ShangHai”;
但以下SQL就可以成功执行
SELECT city FROM t4 AS c WHERE c.city
= ‘ShangHai’;
这是因为FROM是最先执行的,所以可以识别出别名c的
此外,在WHERE过滤器中进行的过滤和在ON过滤器中进行的过滤是有所不同的,对于OUTER JOIN中的过滤,在ON过滤器过滤完之后还会添加保留表中被ON条件过滤掉的记录,因为后面还会进行OUTER JOIN保留表的匹配,但WHERE条件中被过滤掉的记录则是永久的过滤,即使在INNER JOIN中两者也是没有差别的。
SELECT * FROM t4 LEFT JOIN t3 ON t4.city
= t3.city
;
其实OUTER JOIN ON 其实是ON先处理数据,然后OUTER JOIN 补回保留表的数据。
5、分组(GROUP BY)
在本步骤中根据指定的列对上个虚拟表进行分组,最后得到虚拟表VT5。
GROUP BY要注意的点就是NULL = NULL(前面已经提过)
不过要注意的是,使用OUTER JOIN之后再使用GROUP BY,不太建议使用COUNT,比如COUNT(1)、COUNT(*),因为会把保留表的行也会加进去,导致数据不准
比如,这是t3表
这是t4表
然后进行下列SQL
//t4作为保留表
SELECT COUNT(1) FROM t4 LEFT JOIN t3 ON t4.city
= t3.city
GROUP BY t4.city
;
结果显示产生4组,没组都有一条数据,这就证明了,t4保留表的QingHai在聚合时,独自分在一组
6、应用ROLLUP或CUBE
如果指定了ROLLUP选项,那么将创建一个额外的记录添加到虚拟表VT5的最后,并且生成虚拟表VT6。
对于CUBE选项,Mysql并没有实现,也就是并不支持CUBE操作,只是SQL中是有的。
7、应用HAVING过滤器
HAVING过滤器已经是最后一个条件过滤器了,之前已经经过了ON和HAVING的过滤器,HAVING过滤器是对分组条件进行过滤的筛选器,也就是对GROUP BY形成的块组进行过滤,后面的条件不一定是一个聚合,也可以是普通的条件匹配。
注意
子查询不可以用于做分组的聚合函数,比如HAVING COUNT(SELECT …) < 2是不符合的。
8、处理SELECT列表
虽然SELECT是查询中最先被指定的部分,即是顺序排在第一,但是直到现在步骤8才进行处理SELECT列表,这一步中,将SELECT中指定的列从上一步产生的虚拟表中选出。
先自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以扫码领取!
![img](https://img-blog.csdnimg.cn/img_convert/77862129d367d0cd0c9e7d4c0ae3c755.jpeg)
最后
金三银四到了,送上一个小福利!
😕/img-community.csdnimg.cn/images/e5c14a7895254671a72faed303032d36.jpg" alt=“img” style=“zoom: 33%;” />
最后
金三银四到了,送上一个小福利!
[外链图片转存中…(img-W5NxI0iv-1711403822378)]
[外链图片转存中…(img-1BAkrNVw-1711403822378)]
[外链图片转存中…(img-PCPxzSIF-1711403822378)]
需要更多Java资料的小伙伴可以帮忙点赞+关注,点击传送门,即可免费领取!