聚合函数
与其他查询不同,普通的查询做的都是横向查询,它们都是根据条件一行一行的进行判断,而使用聚合函数查询是纵向查询,
它是对一列的值进行计算,然后返回一个单一的值;另外聚合函数会忽略空值。
从案例引出问题:
我们基于以上表作为查询:
select count(*) from product;
-- 返回18 没有任何问题
select pid,min(price) from product ;
select pid,max(price) from product ;
-- 此时不报错 pid显示结果都为1
Q;为什么会产生这种现象?
因为聚合函数是对列进行操作和pid字段没有产生联系 ,系统pid默认的值全为1
此时我们可以考虑子查询+AND 来解决类似hive里的窗口函数的功能
select pid ,price from product where price = (select min(price) from product);
聚合函数一般会和分组查询group by 结合使用
格式:
select 字段1,字段2… from 表名 group by 分组字段 having 分组条件;
-- 1 统计各个分类商品的个数
select category_id ,count(*) from product group by category_id ;
执行结果如上:
执行顺序是先分组 再进行count聚合
注意:如果要进行分组的话,则SELECT子句之后,只能出现分组的字段和统计函数,其他的字段不能出现
having与where的区别
分组之后对统计结果进行筛选的话必须使用having,不能使用where
where子句用来筛选 FROM 子句中指定的操作所产生的 行
group by 子句用来分组 WHERE 子句的输出。
having 子句用来从分组的结果中筛选行
select category_id ,count(*) from product where price>300 group by category_id having count(*) > 3;
select category_id ,count(*) from product group by category_id having count(*) > 3;
-- 思考以上语句哪条会有问题?
-- 答案是都没问题 where首先把不满足的行去掉后进行分组,筛选出特定的组
-- 另一个也是将条件不满足的筛选掉 只不过是分组后进行 顺序问题
-- 执行顺序where>group by>count(*) > having
一些注意的点
mysql 5.6环境下除了count(*)为特例(不忽略null值)外,其余聚集函数确实是忽略null值
聚合函数默认忽略字段为null的记录 要想列值为null的记录也参与计算,必须使用ifnull函数对null值做替换 这里不做过多演示
使用Group By子句返回的组没有特定的顺序,可以使用Order By子句指定次序。
group by和order by连用的确会出现问题
Group by中子查询order by排序失效问题分析
依然要考虑执行顺序
获取sql分组中id最大的记录
select id,name from (select id,name from tt order by id desc) as t group by name
从from开始执行顺序 group by的执行顺序> select 每个组默认取了第一条数据。
// 表数据如下:
id,name
1,name1
2,name1
3,name2
4,name2
select id,name from (select id,name from tt order by id desc) as t group by name
// 输出结果如下:
id,name
1,name1
3,name2
这是为什么呢?因为mysql 5.6之后版本对排序的sql解析做了优化,子查询中的排序是会被忽略的,所以上面的order by id desc未起到作用。如果子语句中排序不做优化那不就可以了么,查阅资料发现可以在子语句中加上limit来避免这种优化(加上limit相当于临时表限定了取值范围不会进行优化,如果是全表的话就被优化掉了)。
正确写法:
// 加上limit
select id,name from (select id,name from tt order by id desc limit 1024) as t group by name
// 输出结果如下:
id,name
2,name1
4,name2