mysql中的聚合函数易混淆的概念


聚合函数

与其他查询不同,普通的查询做的都是横向查询,它们都是根据条件一行一行的进行判断,而使用聚合函数查询是纵向查询,

它是对一列的值进行计算,然后返回一个单一的值;另外聚合函数会忽略空值。

从案例引出问题:

我们基于以上表作为查询:

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

文章作者: liming
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 liming !
评论
  目录