【MySQL基础教程】分组聚集

1.环境搭建

CREATE TABLE `temp` (
  `key` char(1) DEFAULT NULL,
  `value` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO temp ( `key`, `value` )
VALUES
    ( 'A', 1 ),( 'A', 2 ),( 'A', 3 ),( 'A', 9 ),( 'A', 9 ),
    ( 'B', 10 ),( 'B', 12 ),( 'B', 63 ),( 'B', 19 ),( 'B', 9 ),
    ( 'C', 60 ),( 'C', 112 ),( 'C', 6 ),( 'C', 9 ),( 'C', 99 ),
    ( 'D', NULL ),( 'D', NULL ),( 'D', NULL ),( 'D', NULL ),( 'D', NULL );

2.聚合函数(组函数)

2.1 COUNT

count用于统计次数,可以用于所有类型的字段或常量。

SELECT
    `KEY`,
    COUNT(*) count01, # 统计出现次数
    COUNT(`KEY`) count02, # 可以引用某个字段用于统计
    COUNT(`value`) count03, # 但是null不计算次数
    COUNT(DISTINCT `value`) count04 # 加上DISTINCT关键字,可以去除重复,得到不同值的数量
FROM
    temp
GROUP BY
    `KEY`;
/*
+-----+---------+---------+---------+---------+
| KEY | count01 | count02 | count03 | count04 |
+-----+---------+---------+---------+---------+
| A   |       5 |       5 |       5 |       4 |
| B   |       5 |       5 |       5 |       5 |
| C   |       5 |       5 |       5 |       5 |
| D   |       5 |       5 |       0 |       0 |
+-----+---------+---------+---------+---------+
4 rows in set (0.04 sec)
*/

2.2 SUM、AVG

sum用于求和,avg用于取平均值,尽可能传递数值类字段/常量。

SELECT
    `KEY`,
    SUM(`value`) sum01, # 对某个字段求和,null会被忽略
    SUM(1) sum02, # 也可以传递常量,sum(n)等于count(*)*n
    SUM(DISTINCT `value`) sum03, # 加上DISTINCT关键字,可以去除重复
    AVG(`value`) avg01, # 对某个字段去平均值,null会被忽略
    AVG(1) avg02, # 也可以传递常量,但是没有实际意义,avg(n)等于n
    AVG(DISTINCT `value`) avg03, # 加上DISTINCT关键字,可以去除重复
    SUM(`value`) / COUNT(`value`) sc01, # avg等效于sum/count
    SUM(DISTINCT `value`) / COUNT(DISTINCT `value`) sc02,
    SUM(`KEY`) sumstr01, AVG(`KEY`) avgstr01, # 如果传递非数值类参数,会自动转换类型
    SUM('1abc2') sumstr02, AVG(CAST('1abc2' AS SIGNED)) avgstr02 # Mysql的转换机制是"尽力而为",无论隐式还是显式
FROM
    temp
GROUP BY
    `KEY`;
/*
+-----+-------+-------+-------+---------+--------+---------+---------+---------+----------+----------+----------+----------+
| KEY | sum01 | sum02 | sum03 | avg01   | avg02  | avg03   | sc01    | sc02    | sumstr01 | avgstr01 | sumstr02 | avgstr02 |
+-----+-------+-------+-------+---------+--------+---------+---------+---------+----------+----------+----------+----------+
| A   | 24    | 5     | 15    | 4.8000  | 1.0000 | 3.7500  | 4.8000  | 3.7500  |        0 |        0 |        5 | 1.0000   |
| B   | 113   | 5     | 113   | 22.6000 | 1.0000 | 22.6000 | 22.6000 | 22.6000 |        0 |        0 |        5 | 1.0000   |
| C   | 286   | 5     | 286   | 57.2000 | 1.0000 | 57.2000 | 57.2000 | 57.2000 |        0 |        0 |        5 | 1.0000   |
| D   | NULL  | 5     | NULL  | NULL    | 1.0000 | NULL    | NULL    | NULL    |        0 |        0 |        5 | 1.0000   |
+-----+-------+-------+-------+---------+--------+---------+---------+---------+----------+----------+----------+----------+
4 rows in set (0.06 sec)
*/

2.3 MIN、MAX

SELECT
    MAX(`KEY`) MAX01, # MAX用于获取最大值
    MAX(`value`) MAX02, # NULL依然会被忽略
    MAX(DISTINCT `KEY`) MAX03, # 支持DISTINCT关键字,但是没有实际意义
    MIN(`KEY`) MIN01, # MIN用于获取最小值,用法和注意事项与MAX完全一致
    MIN(`value`) MIN02,
    MIN(DISTINCT `KEY`) MIN03
FROM
    temp;
/*
+-------+-------+-------+-------+-------+-------+
| MAX01 | MAX02 | MAX03 | MIN01 | MIN02 | MIN03 |
+-------+-------+-------+-------+-------+-------+
| D     |   112 | D     | A     |     1 | A     |
+-------+-------+-------+-------+-------+-------+
1 row in set (0.06 sec)
*/

2.4 小结

相同点:

  1. 仅允许传递一个参数/常量
  2. 会忽略null
  3. 可以使用distinct关键字去重

不同点:

  1. 只有count允许传递*

注意:

上述5种聚合函数,不允许嵌套,例如MAX(MIN(1))。

此外mysql提供了一个拼接字符串的聚合函数group_concat,可参阅:【MySQL基础教程】字符串处理函数

3.GROUP BY

SELECT
    `KEY`,
    COUNT(*) count01
FROM
    temp
GROUP BY
    `KEY`, CONCAT('KEY IS ', `KEY`), 'KEY' # 指定分组字段,允许多个字段组合分组,支持表达式和常量,但是传递常量无意义
    ;
/*
+-----+---------+
| KEY | count01 |
+-----+---------+
| A   |       5 |
| B   |       5 |
| C   |       5 |
| D   |       5 |
+-----+---------+
4 rows in set (0.05 sec)
*/

SELECT
    `KEY` KEYWORD,
    COUNT(*) count01
FROM
    temp
GROUP BY
    KEYWORD # 也支持使用别名分组
    ;
/*
+---------+---------+
| KEYWORD | count01 |
+---------+---------+
| A       |       5 |
| B       |       5 |
| C       |       5 |
| D       |       5 |
+---------+---------+
4 rows in set (0.05 sec)
*/

SELECT
    `KEY` KEYWORD,
    COUNT(*) count01
FROM
    temp
GROUP BY
    1 # 还支持使用字段序号,从1开始
    ;
/*
+---------+---------+
| KEYWORD | count01 |
+---------+---------+
| A       |       5 |
| B       |       5 |
| C       |       5 |
| D       |       5 |
+---------+---------+
4 rows in set (0.05 sec)
*/


SELECT
    `KEY` KEYWORD,
    COUNT(*) count01
FROM
    temp
GROUP BY
    1 DESC # 还可以写入排序,简化SQL语句
    ;
/*
+---------+---------+
| KEYWORD | count01 |
+---------+---------+
| D       |       5 |
| C       |       5 |
| B       |       5 |
| A       |       5 |
+---------+---------+
4 rows in set (0.05 sec)
*/


SELECT
    `KEY`,
    `value`,
    COUNT(*) count01
FROM
    temp
GROUP BY
    `KEY`, `value`
WITH ROLLUP # 带上WITH ROLLUP,可以实现小计+总计的功能:分别以KEY+VALUE,KEY,NULL(可以看成是常量,所有数据在一个组中)分组
    ;
+------+-------+---------+
| KEY  | value | count01 |
+------+-------+---------+
| A    |     1 |       1 |
| A    |     2 |       1 |
| A    |     3 |       1 |
| A    |     9 |       2 |
| A    | NULL  |       5 |
| B    |     9 |       1 |
| B    |    10 |       1 |
| B    |    12 |       1 |
| B    |    19 |       1 |
| B    |    63 |       1 |
| B    | NULL  |       5 |
| C    |     6 |       1 |
| C    |     9 |       1 |
| C    |    60 |       1 |
| C    |    99 |       1 |
| C    |   112 |       1 |
| C    | NULL  |       5 |
| D    | NULL  |       5 |
| D    | NULL  |       5 |
| NULL | NULL  |      20 |
+------+-------+---------+
20 rows in set (0.06 sec)

4.HAVING

SELECT
    `KEY`,
    COUNT(*) count01
FROM
    temp
GROUP BY
    `KEY`
HAVING
    SUM(`VALUE`) > 100 # 过滤数据,语法与WHERE一致,但是HAVING是在分组聚合之后过滤,WHERE在GROUP BY之前
    ;
/*
+-----+---------+
| KEY | count01 |
+-----+---------+
| B   |       5 |
| C   |       5 |
+-----+---------+
2 rows in set (0.05 sec)
*/


SELECT
    `KEY`,
    COUNT(*) count01
FROM
    temp
HAVING
    SUM(`VALUE`) > 100 # 如果在没有GROUP BY字句的情况下使用HAVING,相当于GROUP BY 常量,所有的数据会放在一个组中
    ;
/*
+-----+---------+
| KEY | count01 |
+-----+---------+
| A   |      20 |
+-----+---------+
1 row in set (0.05 sec)
*/


SELECT
    `KEY`,
    COUNT(*) count01
FROM
    temp
GROUP BY
    `KEY`
HAVING
    `value` < 100 # 既没有出现在GROUP BY字句,又没有使用聚合函数包裹的列,不能使用HAVING过滤
    ;
/*
1054 - Unknown column 'value' in 'having clause'
*/

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值