数据库中having和where的用法和区别
一、group by和order by的用法与区别
在讲having和where在数据库中的区别前,我们可以先梳理一下group by和order by的区别。(若已了解可跳过)
- group by:分组。group by后面接字段名,即:根据该 字段名 进行 分组。
- order by:排序。order by后面接字段名,即:根据该 字段名 进行 排序。
根据以下该表举例
(1)order by
#order by(例)
#(单个)根据 分类id 进行 排序
select category_id,name,price
from sh_goods
order by category_id;
#(多个)根据 分类id和评分 进行 排序
select category_id,name,score,price
from sh_goods
order by category_id,score desc;
#在字段名后+asc(升序)/desc(降序),若不加,即默认升序
#每个字段都是单独加asc/desc
(2)group by
#group by(例)
#聚合函数可以对字段进行分类
#(单个)根据 分类id 进行 分类
select id,group_concat(name),count(category_id)
from sh_goods
group by category_id;
select id,score,group_concat(name),count(category_id)
from sh_goods
group by category_id,score; #(多个)根据 分类id和评分 进行 分类
这里附上常用的聚合函数:
二、having和where的用法和区别
相同点:
都是用于 筛选条件 的关键字
不同点:
- having:对 分组后 的数据进行筛选,即用在
group by后
where:对 分组前 的数据进行筛选,即用在
group by 前 - where后面的条件不能加聚合函数,即where不能对分过组的数据进行判断,而having可以。
接下来用一道题说明having和where的用法和顺序
题目:在sh_goods表中查询评分小于4的商品的不同分类id 的商品个数
用法和顺序
#单独用where筛选时
select category_id,score,group_concat(name),count(category_id)
from sh_goods
where score < 4 #
group by category_id
order by category_id;
#单独用having时
select category_id,score,group_concat(name),count(category_id)
from sh_goods
group by category_id,score
#这里不加order by,因为会有关键字冲突
having score < 4;
结果都为下图:
这里会有几个问题
-
虽然都得到了正确答案,但是到底用哪个更好?
这个问题关键在于:用where和having是否符合题目要求。
题目要求用 分类id 进行分组,从而筛选到 评分小于4 的 商品,并统计在这一条件下 相同分类id的商品个数。
可以看到上图中的having虽然也得到了正确答案,但它用了两个分组,才筛选出正确答案,显然不符合要求。
那么你会想到如果我直接用分类id筛选不能得出正确答案吗?
这就是我们要说的第二个问题,你会发现当你去掉score这一分组,你缺少分类id为3的那一行数据。 -
所以为什么当用having,且只用 分类id 分组时,得不到题目所要的正确结果?
当你用group by category_id语句时,分类id为3的数据中,会将其他列的数据默认为 第一组数据。
那么score就会默认成 4.9。
如下图:
所以这就是为什么用having时,筛选score < 4,你无法对已经分好类的数据筛选出这道题中 分类id 为3 的原因。
这其中是逻辑的错误,所有这道题最终是用where筛选更合适。
where在分组之前对所有 category_id 中 score<4 进行一个筛选,那这样就可以得到完整的答案。