分组查询(GROUP BY)
字面上意思很简单就是分组查询 , 它可以将查询结果按照某个字段或多个字段进行分组。字段中值相等的为一组. MySQL中GROUP BY语句用于对某个或某些字段查询分组,并返回这个字段重复记录的第一条,也就是每个小组(无排序)里面的第一条。
基本语法
GROUP BY 属性名 [HAVING 条件表达式] [WITH ROLLUP]
- 属性名:是指按照该字段的值进行分组。
- HAVING 条件表达式:用来限制分组后的显示,符合条件表达式的结果将被显示。
- WITH ROLLUP:将会在所有记录的最后加上一条记录。加上的这一条记录是上面所有记录的总和
使用场景
GROUP BY关键字通常与集合函数一起使用。
- COUNT()函数:用于统计记录的条数。
- SUM()函数:用于计算字段的值的总和。
- AVG()函数:用于计算字段的值的平均值。
- MAX()函数:用于查询字段的最大值。
- MIN()函数:用于查询字段的最小值。
GROUP BY关键字可以和GROUP_CONCAT()函数一起使用。GROUP_CONCAT()函数会把每个分组中指定的字段值都显示出来。
下面我们来看下实际的应用场景,准备一张店铺关系表
基本使用
1,最基本的分组,(单个字段分组)
SELECT * from sub_shop_relation GROUP BY user_id
这里我们看到只有三条记录产生,上面我们说到,在不使用集合函数的情况下,默认返回分组的第一天数据.
2,最基本的分组,(多个字段分组)
SELECT * from sub_shop_relation GROUP BY user_id,site
多个字段的分组逻辑就是按照(site,user_id)两个字段进行分组,只要这两个字段其中一个字段未重复就是分一个组,我们表中的有两条数据是这两个字段都重复的,所以他会舍弃最后一条,保留第一条.
3,group by 配合 group_concat()函数使用,(追加显示字段)
SELECT site , GROUP_CONCAT(name) name from sub_shop_relation GROUP BY site
上面这个查询的逻辑是,根据 site 进行分组,然后追加显示每一个分组里面的 name ,比如说 再MY这个分组里面存在张三和王五这两个用户,就很好的将分组情况展示出来了
配合集合函数使用
1.group by 配合 count()使用 ,(统计总记录数)
SELECT name ,COUNT(name) num from sub_shop_relation GROUP BY name
上面是根据名字进行分组,并且统计分组里面的名字数量,例如 张三出现了两次,李四出现了3次
2.group by 配合 sum()使用 ,(计算字段值的总和)
SELECT site, SUM(sales) sales from sub_shop_relation GROUP BY site
上面的查询逻辑是先根据站点进行分组,然后统计这些站点的销售量.例如MY站点出现了两次 一次100,一次是200,分组后就是他们加起来 300.
3.group by 配合 avg()使用 ,(计算平均值)
SELECT name,AVG(sales) sales from sub_shop_relation GROUP BY name
这里的查询逻辑是现根据名字进行分组,然后再求分组里面sales的平均值,例如王五的各个站点的sales分别是 300,100,200.分组后就将他们加起来,再求平均值,得出 200 的sales
4.group by 配合 max/min()使用 ,(计算分组里面的最大/小值)
SELECT name,max(sales) sales from sub_shop_relation GROUP BY name
SELECT name,min(sales) sales from sub_shop_relation GROUP BY name
上面就是分组后获取组内的最大值或者最小值
复杂分组查询(having子句)
复杂分组查询是在分组之后,存在过滤条件,此时需要使用having子句。在 SQL 中增加 HAVING 子句原因是,WHERE
关键字无法与聚合函数一起使用。
HAVING 子句可以让我们筛选分组后的各组数据。其基本步骤如下:
先进行基础分组查询
添加分组前筛选条件【where子句】,依据:在原数据表可查询
添加分组后筛选条件【having子句】,依据:只能在分组后的中间结果表中查到,多是分组函数结果
A.查询销售量sales> 200的人名
SELECT name from sub_shop_relation WHERE sales > 200 GROUP BY name
上面的分组查询逻辑是 先查询 sales>200的名字,再根据名字分组,可以看出这里的 where后面的条件再外面源数据表里面是存在的.
查询最小售价 < 200的人名
SELECT name, min(sales) s from sub_shop_relation GROUP BY name HAVING s < 200
他产生再最小售价的分组里面,我门下需要用产生的最小售价再去比一次,所以他不属于原表数据
函数分组group by func()
外面将王五的长度改为3
按姓名长度分组,查询名字长度 >6用户
日常注意事项
若分组函数作为筛选条件,其筛选条件一定是放在having子句中。
优先考虑使用where子句,即分组前筛选。
当字段在原始表中, where子句和having子句都可使用,这种情况优先使用where子句,提高性能.
今天笔记做到这里,后面补充