测试表TEST
ID | NAME | NUMBER |
1 | AA | 2 |
2 | AA | 3 |
3 | BB | 4 |
4 | BB | 5 |
5 | CC | 6 |
6 | DD | 7 |
7 | EE | 7 |
8 | BB | 5 |
9 | CC | 6 |
在这之前先判断底下这几条SQL是否是正确的,为什么?????????
select name from test group by NAME------->TRUE
select * from test group by NAME-------->ERROR
select NAME,sum(NUMBER) from test group by name--------->TRUE
一.单列的Group by
select NAME from test group by name;
结果(这个是表2):
NAME |
AA |
BB |
CC |
DD |
EE |
为了能够更好的理解Group by多个列、聚合函数的应用,由表一到表2的过程增加了一个中间表:虚拟表3。接下来介绍一下如何去思考上面所提道德问题:
1.from test:sql执行的第一步、找表没什么变化
2.from test group by name:没有join和where,就只有group by了,这时候的过程就如下图所示了,找到name的那一列,将具有相同name的值放在同一行。比如name=AA时,就将<1,AA,2>和<2,AA,3>这两行合并在一起,其它字段ID和NUMBER就放在一个单元格里面
ID | NAME | NUMBER |
1 2 | AA | 2 3 |
3 4 8 | BB | 4 5 5 |
5 9 | CC | 6 6 |
6 | DD | 7 |
7 | EE | 7 |
3.接下来就是对虚拟表进行select操作了,这个时候就可以看出上面的几条SQL的区别和错误的原因在哪里了
(1)直接select name是没有问题的,因为group by的字段就是name,每个单元格也只有一个name,没有问题
(2)执行select *的话,因为是从虚拟表中select,ID和NUMBER字段的单元格中都是多个数值,关系型数据库是不允许这样操作的,所以就会报错
(3)针对这种每个单元格有多个数值的这种情况,可以使用聚合函数进行操作,比如Count(ID),SUM(NUMBER),这样的会就不会报错了,所以该SQL也是OK的
由此可见聚合函数和group by之间也是有相当紧密的关系了,哈哈哈哈
二.对多列进行group by
那要是group by多个字段怎么理解呢,比如group by name,number,此时我们可以将name和number看成一个整体的字段,将其作为一个整体来进行判断和划分。如图
ID | NAME | NUMBER |
1 | AA | 2 |
2 | AA | 3 |
3 | BB | 4 |
4 8 | BB | 5 |
5 9 | CC | 6 |
6 | DD | 7 |
7 | EE | 7 |
根据test表来看的话,只有<BB,5>和<CC,6>是NUMBER和NAME的值都相等的,所以可以将其进行合并,此时执行以下SQL
select name,sum(ID) from test group by name,number;
name | SUM(ID) |
AA | 1 |
AA | 2 |
BB | 3 |
BB | 12 |
CC | 14 |
DD | 6 |
EE | 7 |