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子句的力量的主要内容,如果未能解决你的问题,请参考以下文章
从带有 HAVING 子句的 MySQL 视图中选择返回空结果集