文章目录
- 准备`sql`
- 执行
- 分析执行过程
用了很久的
gorup by
一道面试题让我突然觉得自己不会用了。原题是这样的:表A有三个列分别为a、b、c
。语句select a,b,c from A group by 【a、b、c任意一个字段】
会出现什么情况。答案是这样的,不管你是以
a、b、c
哪一个字段来分组,第一条件:分组的依据要么包含在select
后面要么就是聚合函数包含(必须保证分组之后显示的字段是唯一的,含有多个的情况就必须进行聚合)。还有一种情况就是查询结果集只有分组的依据(没有意义)。
# 伪代码表示
(select 包含分组条件 || 聚合函数包含分组条件|| 只查询分组条件进行分组(没有意义)|| 以主键ID进行分组(没有意义))&& 查询显示的结果字段唯一(不能含有多个值)
# 总结: 分组之后的结果有多个的话必须进行聚合
准备sql
drop table if exists `test`;
create table if not exists `test`(
`id` bigint not null auto_increment comment '主键ID',
`name` varchar(10) not null comment '名称',
`count` bigint not null default 10 comment '次数',
primary key (`id`)
)engine=innodb auto_increment = 66 default charset=utf8 comment '测试表';
insert into `test` (`name`,`count`) values ("a",59),
("a",44),
("a",55534),
("b",22),
("c",95468),
("d",66),
("d",43),
("d",76);
执行
-- 不管name是否重复都可以执行但是没有意义
select `name` from `test` group by `name`
-- 都是可以执行的,以主键分组有什么意义呢
select `id`,`count` from `test` group by `id`
select `id`,`name` from `test` group by `id`
select `id`,`name`,`count` from `test` group by `id`
-- 不管name是否唯一都不能执行(name分组之后会有多个结果集需要进行汇聚)
select `id`,`name`,`count` from `test` group by `name`
-- 可以执行
select sum(`id`),`name`,sum(`count`) from `test` group by `name`
-- 不管count是否唯一都不能执行
select `id`,`name`,`count` from `test` group by `count`
-- 可以执行没有意义
select `id`,`name`,`count` from `test` group by `count`,`id`
-- 正确用法
select `name`,sum(`count`) as `count` from `test` group by `name`;
分析执行过程
为了更好的理解
group by
多个列和聚合函数的应用,将从表1到表3的过程模拟出一张中间表表2。
最终返回的结果为表2,但是此时
id
和count
单元格内是有多个值的。我们都知道关系型数据库是不允许一个单元格内存在多个值的。所以当分组之后返回的结果单元格中含有多个值是就出错了。比如说select *
。对于这种含有一个单元格内含有多个值的解决方式就是聚合,把这些多个单元格值聚合为一个,就能正确执行了。