13group by分组

Posted stephanie-boke

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了13group by分组相关的知识,希望对你有一定的参考价值。

group by 分组

  • GROUP BY 语句根据一个或多个列对结果集进行分组。
  • 在分组的列上我们可以使用 COUNT, SUM, AVG,等函数。

1、max 、min 、sum 、avg 、count 使用

类型宽度实例
max 最大值 select max(shop_price) from goods;
min 最小值 select min(shop_price) from goods;
sum 求总和 select sum(good_number) from goods;
avg 求平均 select avg(shop_price) from goods;
count 求总行数 select count(*) from goods;

实现了:

  • 查出最贵的商品
  • 查出最便宜的商品
  • 查出平均价
  • 查询一共有多少种商品,即是求表中有多少行,其中*可以为1,0,及其其他的任意有效字段。

1.1 count 详解

  • count(*)中星号表示任意字段,表示每次数该字段,一共数多少次,当星号用有效字段名替代,且表中有null的时候,数的次数并不是行数,建议直接用星号表示
  • select count(*) from 表名; 查询的就是绝对的行数,哪怕某一行所有字段全为NULL,也计算在内。
  • select count(列名) from 表名; 查询的是该列不为NULL的行数
  • 用count(*),count(1)谁好呢?

    对于myisam引擎的表没有区别,这种引擎内部有一个计数器在维护者行数
    Innodb的表,用count(*)直接读行数,效率很低,因为innodb真的要去数一遍。

代码

create table test8(
id int,
name varchar(20)
)engine myisam charset=utf8;

insert into test8 values (1,‘lisi‘);
insert into test8 values (2,null);

mysql> select count(*) from test8;
+----------+
| count(*) |
+----------+
|        2 |
+----------+
1 row in set

mysql> select count(name) from test8;
+-------------+
| count(name) |
+-------------+
|           1 |
+-------------+
1 row in set

2、函数与where结合使用

建表

DROP TABLE IF EXISTS `employee_tbl`;
CREATE TABLE `employee_tbl` (
  `id` int(11) NOT NULL,
  `name` char(10) NOT NULL DEFAULT ‘‘,
  `date` datetime NOT NULL,
  `singin` tinyint(4) NOT NULL DEFAULT ‘0‘ COMMENT ‘登录次数‘,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

添加数据

INSERT INTO `employee_tbl` VALUES (‘1‘, ‘小明‘, ‘2016-04-22 15:25:33‘, ‘1‘), 
(‘2‘, ‘小王‘, ‘2016-04-20 15:25:47‘, ‘3‘), (‘3‘, ‘小丽‘, ‘2016-04-19 15:26:02‘, ‘2‘),
(‘4‘, ‘小王‘, ‘2016-04-07 15:26:14‘, ‘4‘), (‘5‘, ‘小明‘, ‘2016-04-11 15:26:40‘, ‘4‘),
(‘6‘, ‘小明‘, ‘2016-04-04 15:26:54‘, ‘2‘);
COMMIT;

mysql> select * from employee_tbl;
+----+------+---------------------+--------+
| id | name | date                | singin |
+----+------+---------------------+--------+
|  1 | 小明 | 2016-04-22 15:25:33 |      1 |
|  2 | 小王 | 2016-04-20 15:25:47 |      3 |
|  3 | 小丽 | 2016-04-19 15:26:02 |      2 |
|  4 | 小王 | 2016-04-07 15:26:14 |      4 |
|  5 | 小明 | 2016-04-11 15:26:40 |      4 |
|  6 | 小明 | 2016-04-04 15:26:54 |      2 |
+----+------+---------------------+--------+
6 rows in set

count 与 where 结合,计算小明出现的次数
select count(*) from employee_tbl where name=‘小明‘;

问题:
我们能知道,小明出现的次数,也能知道小王出现的次数,但是如何一次查询他们各自出现的次数呢?

3、GROUP BY 语法

SELECT column_name, function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name;

3.1、group by 实例

查询小明、小王、小丽个自登录的次数,意味者需要根据名字分组

mysql> select name, sum(singin) from employee_tbl group by name;
+------+-------------+
| name | sum(singin) |
+------+-------------+
| 小明 | 7           |
| 小王 | 7           |
| 小丽 | 2           |
+------+-------------+
3 rows in set

3.2、使用 with rollup

  • WITH ROLLUP 可以实现在分组统计数据基础上再进行相同的统计(SUM,AVG,COUNT…)。

例如我们将以上的数据表按名字进行分组,再统计每个人登录的次数:

mysql> SELECT name, SUM(singin) as singin_count FROM  employee_tbl GROUP BY name WITH ROLLUP;
+------+--------------+
| name | singin_count |
+------+--------------+
| 小丽 | 2            |
| 小明 | 7            |
| 小王 | 7            |
| NULL | 16           |
+------+--------------+
4 rows in set

其中记录 NULL 表示所有人的登录次数。 我们可以使用 coalesce 来设置一个可以取代 NUll 的名称,coalesce 语法:

select coalesce(a,b,c);

参数说明:如果a==null,则选择b;如果b==null,则选择c;如果a!=null,则选择a;如果a b c 都为null ,则返回为null(没意义)。

以下实例中如果名字为空我们使用总数代替:

mysql> SELECT coalesce(name, ‘总数‘), SUM(singin) as singin_count FROM  employee_tbl GROUP BY name WITH ROLLUP;
+--------------------------+--------------+
| coalesce(name, ‘总数‘) | singin_count |
+--------------------------+--------------+
| 小丽                   |            2 |
| 小明                   |            7 |
| 小王                   |            7 |
| 总数                   |           16 |
+--------------------------+--------------+
4 rows in set (0.01 sec)

4、易错语句判断

4.1 select name, sum(singin) from employee_tbl;

显示:1140 - In aggregated query without GROUP BY...
name 与 sum(singin) 不匹配。

改正:select name, sum(singin) from employee_tbl group by name;

严格的讲,select的a,d列必须在group by 的 a,b,c 列里出现
也就是说,以group by a,b,c 为列,则select的列,只能在a,b,c里选择语义上才没有矛盾。

以上是关于13group by分组的主要内容,如果未能解决你的问题,请参考以下文章

Hadoop实战-MapReduce之分组(group-by)统计

如何在不使用 GROUP BY 子句的情况下对行进行分组

.NET(C#) System.Linq中实现多列group by(分组)的示例代码

GROUP BY - 排序前后分组

SQL多次分组问题 group by

FlaskSqlalchemy group_by having