今天在刷牛客的SQL练习题时,碰到了having关键字,由于好久没使用了,所以借此写篇文章记录一下having的用法。
题目链接在此:SQL19
题目:现在运营想查看每个学校用户的平均发贴和回帖情况,寻找低活跃度学校进行重点运营,请取出平均发贴数低于5的学校或平均回帖数小于20的学校。
表结构:
解释一下单行数据:id为7的用户,使用的设备id为4321,性别为男,年龄26岁,复旦大学,gpa为3.6,在过去的30天里面活跃了9天,发帖数量为6,回答数量为52。
根据示例,查询结果应返回的数据如下:
表格解释:
平均发贴数低于5的学校或平均回帖数小于20的学校有2个
属于北京大学的用户的平均发帖量为2.500,平均回答数量为21.000
属于浙江大学的用户的平均发帖量为1.000,平均回答数量为2.000
编写的SQL语句:
select * from
(
select
university,
avg(round(question_cnt, 3)) as avg_question_cnt,
avg(round(answer_cnt, 3)) as avg_answer_cnt
from
user_profile
group by
university
) as t
where
t.avg_question_cnt < 5 or t.avg_answer_cnt < 20;
首先通过对学校字段分组查询得到辅助表,设为t,然后再对辅助表进行条件查询,即可得到结果。
但上面sql语句太长,其实还是可以优化的,这里得搞懂where和having的区别
where与having区别?
- 执行时机不同。where是分组之前进行过滤,即查询的是from后面的表,并且不满足where条件,不参与分组;而having是分组之后对结果进行过滤,是根据辅助表进行条件查询的;
- 判断条件不同。where不能对聚合函数进行判断,即where后面不能使用聚合函数,而having可以。
优化后的SQL语句:
select
university,
avg(round(question_cnt, 3)) as avg_question_cnt,
avg(round(answer_cnt, 3)) as avg_answer_cnt
from
user_profile
group by
university
having
avg_question_cnt < 5 or avg_answer_cnt < 20