mysql Having子句的力量

Posted PHP在线

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了mysql Having子句的力量相关的知识,希望对你有一定的参考价值。

1.查询不包含NULL的集合

COUNT函数的使用方法有COUNT(*)和COUNT(列名)两种,它们的区别有两个:第一个是性能上的区别;第二个是COUNT(*)可以用于NULL,而COUNT(列名)与其他聚合函数一样,要先排除掉NULL的行再进行统计。第二个区别也可以这么理解:COUNT(*)查询的是所有行的数目,而COUNT(列名)查询的则不一定是。对一张全是NULL的表NullTbl执行SELECT子句就能清楚地知道两者的区别了。

在对包含null的列使用时,count(*)和count(列名)查询的结果是不一样的。

SELECT COUNT(*),COUNT(col) FROM A;

对于这两个区别,在编写SQL语句时我们当然需要多加留意,但是如果能好好利用,它们也可以发挥令人意想不到的作用。例如,这里有一张存储了学生提交报告的日期的表Students,如下所示。



学生提交报告后,“提交日期”列会被写入日期,而提交之前是NULL。现在我们需要从这张表里找出哪些学院的学生全部都提交了报告(即理学院、经济学院)。如果只是用WHEREsbmt_date IS NOT NULL这样的条件查询,文学院也会被包含进来,结果就不正确了(因为文学院学号为102的学生还没有提交)。正确的做法是,以“学院”为GROUP BY的列生成下面这样的子集。

所有学生都提交了报告的学院有哪些

这样生成的4个子集里,我们想要的是S1和S4。那么,这2个子集具备而其他子集不具备的特征是什么呢?答案是“COUNT(*)和COUNT(sbmt_date)结果一致”。这是因为S2和S3这2个子集里存在NULL。因此,答案应该是下面这样。

SELECT dpt FROM Students GROUP BY dpt HAVING COUNT(*) = COUNT(sbmt_date);

当然,使用CASE表达式也可以实现同样的功能,而且更加通用。

SELECT dpt FROM Students GROUP BY dpt HAVING COUNT(*) = SUM(CASE WHEN sbmt_date IS NOT NULL THEN 1 ELSE 0 END);

可以看到,使用CASE表达式时,将“提交日期”不是NULL的行标记为1,将“提交日期”为NULL的行标记为0。在这里,CASE表达式的作用相当于进行判断的函数,用来判断各个元素(=行)是否属于满足了某种条件的集合。这样的函数我们称为特征函数(characteristic function),或者从定义了集合的角度来将它称为定义函数。

下面是本节要点。

1.表不是文件,记录也没有顺序,所以SQL不进行排序。

2.SQL不是面向过程语言,没有循环、条件分支、赋值操作。

3.SQL通过不断生成子集来求得目标集合。SQL不像面向过程语言那样通过画流程图来思考问题,而是通过画集合的关系图来思考。

4.GROUP BY子句可以用来生成子集。

5.WHERE子句用来调查集合元素的性质,而HAVING子句用来调查集合本身的性质。

以上是关于mysql Having子句的力量的主要内容,如果未能解决你的问题,请参考以下文章

MySQL之指定过滤条件(HAVING)

MySQL?having子句

从带有 HAVING 子句的 MySQL 视图中选择返回空结果集

查询(HAVING 子句)在 Mysql 版本 5.7 和 8.0 之间的行为不同

mysql group by having 子句

MySQL的语法高级之SELECT