一、概述
题外话:MYSQL
这个东西在工作前都用得少,因为在学校也没怎么学习过,就学了一点很浅的,了解有这个东西。然后后来自学才勉强算是把”增删改查“ 这四个基本操作学会,工作之后才发现远远不够,后面疯狂补才把一些稍微高级一点的东西学会。分组这个东西应该算是高级的东西了吧,用处也是十分广泛,工作后接触到现在用了几个月,算是能灵活运用,现在再把它写出来一是为了回顾,二是因为博客里数据库相关的东西太少了,加点料吧。
数据库中分组的意思是通过一定和规则和约束把有共同特性的数据都合并成一个组,然后以组为单元进行数据操作,当分组字段中的值一样时,数据将被合并成一条记录。
测试数据表:
1 2 3 4 5 6 7 8 |
create table user_info( id int primary key auto_increment, username varchar(16) not null default "" comment "用户名", mobile varchar(11) not null default "" comment "手机号", city varchar(16) not null default "" comment "城市", age int not null default 0 comment "年龄", addr text not null comment "住址" ); |
测试数据:
1 2 3 4 5 6 7 |
insert into user_info values(1, "小明", "13366668881", "长沙", 20, "衡阳"); insert into user_info values(2, "小刚", "13366668882", "广州", 21, "邵阳"); insert into user_info values(3, "小红", "13366668883", "北京", 20, "广州"); insert into user_info values(4, "小黑", "13366668884", "上海", 18, "广州"); insert into user_info values(5, "小白", "13366668885", "北京", 20, "珠海"); insert into user_info values(6, "小华", "13366668886", "长沙", 30, "上海"); insert into user_info values(7, "小李", "13366668887", "长沙", 23, "北京"); |
1 2 3 4 5 6 7 8 9 10 11 12 |
mysql> select * from user_info; +----+----------+-------------+------+-----+------+ | id | username | mobile | city | age | addr | +----+----------+-------------+------+-----+------+ | 1 | 小明 | 13366668881 | 长沙 | 20 | 衡阳 | | 2 | 小刚 | 13366668882 | 广州 | 21 | 邵阳 | | 3 | 小红 | 13366668883 | 北京 | 20 | 广州 | | 4 | 小黑 | 13366668884 | 上海 | 18 | 广州 | | 5 | 小白 | 13366668885 | 北京 | 20 | 珠海 | | 6 | 小华 | 13366668886 | 长沙 | 30 | 上海 | | 7 | 小李 | 13366668887 | 长沙 | 23 | 北京 | +----+----------+-------------+------+-----+------+ |
二、基本用法
2.1 单个字段分组
使用分组的语法:GROUP BY FIEL
,例如根据city
字段分组的SQL语句为:select * from user_info group by city
。
分组后, 查询结果会把城市相同的记录合并成一条记录:
1 2 3 4 5 6 7 8 9 10 |
mysql> select * from user_info group by city; +----+----------+-------------+------+-----+------+ | id | username | mobile | city | age | addr | +----+----------+-------------+------+-----+------+ | 4 | 小黑 | 13366668884 | 上海 | 18 | 广州 | | 3 | 小红 | 13366668883 | 北京 | 20 | 广州 | | 2 | 小刚 | 13366668882 | 广州 | 21 | 邵阳 | | 1 | 小明 | 13366668881 | 长沙 | 20 | 衡阳 | +----+----------+-------------+------+-----+------+ 4 rows in set |
根据年龄分组,所有相同的年龄也会被合并成一条记录:
1 2 3 4 5 6 7 8 9 10 |
mysql> select * from user_info group by age; +----+----------+-------------+------+-----+------+ | id | username | mobile | city | age | addr | +----+----------+-------------+------+-----+------+ | 4 | 小黑 | 13366668884 | 上海 | 18 | 广州 | | 1 | 小明 | 13366668881 | 长沙 | 20 | 衡阳 | | 2 | 小刚 | 13366668882 | 广州 | 21 | 邵阳 | | 7 | 小李 | 13366668887 | 长沙 | 23 | 北京 | | 6 | 小华 | 13366668886 | 长沙 | 30 | 上海 | +----+----------+-------------+------+-----+------+ |
2.2 多字段分组
多字段分组的格语法是:GROUP BY FIELD_A, FIELD_B
,只有同时满足两个字段约束的时候才会被合并,也就是说只有A和B都相等的数据才能被合并。
1 2 3 4 5 6 7 8 9 10 11 |
mysql> select * from user_info group by city, age; -- 根据`city` 和 `age` 分组 +----+----------+-------------+------+-----+------+ | id | username | mobile | city | age | addr | +----+----------+-------------+------+-----+------+ | 4 | 小黑 | 13366668884 | 上海 | 18 | 广州 | | 3 | 小红 | 13366668883 | 北京 | 20 | 广州 | | 2 | 小刚 | 13366668882 | 广州 | 21 | 邵阳 | | 1 | 小明 | 13366668881 | 长沙 | 20 | 衡阳 | | 7 | 小李 | 13366668887 | 长沙 | 23 | 北京 | | 6 | 小华 | 13366668886 | 长沙 | 30 | 上海 | +----+----------+-------------+------+-----+------+ |
可以看到,id等于3和5的两条记录,city
和age
都是相同的,在经过分组后被合并成了一个记录。
要注意的是多字段分组时,字段有先后顺序,根据city, age
分组和根据age, city
分组的结果是不一样的。
1 2 3 4 5 6 7 8 9 10 11 |
mysql> select * from user_info group by age, city; -- 根据age, city分组 +----+----------+-------------+------+-----+------+ | id | username | mobile | city | age | addr | +----+----------+-------------+------+-----+------+ | 4 | 小黑 | 13366668884 | 上海 | 18 | 广州 | | 3 | 小红 | 13366668883 | 北京 | 20 | 广州 | | 1 | 小明 | 13366668881 | 长沙 | 20 | 衡阳 | | 2 | 小刚 | 13366668882 | 广州 | 21 | 邵阳 | | 7 | 小李 | 13366668887 | 长沙 | 23 | 北京 | | 6 | 小华 | 13366668886 | 长沙 | 30 | 上海 | +----+----------+-------------+------+-----+------+ |
2.3 排序
使用分组的时候可以进行排序操作,语法为:GROUP BY ** ORDER BY **
1 2 3 4 5 6 7 8 9 10 |
mysql> select * from user_info group by age order by age; -- 根据分组后的年龄排序 +----+----------+-------------+------+-----+------+ | id | username | mobile | city | age | addr | +----+----------+-------------+------+-----+------+ | 4 | 小黑 | 13366668884 | 上海 | 18 | 广州 | | 1 | 小明 | 13366668881 | 长沙 | 20 | 衡阳 | | 2 | 小刚 | 13366668882 | 广州 | 21 | 邵阳 | | 7 | 小李 | 13366668887 | 长沙 | 23 | 北京 | | 6 | 小华 | 13366668886 | 长沙 | 30 | 上海 | +----+----------+-------------+------+-----+------+ |
排序不限于分组字段,可以根据A字段分组,然后根据B字段排序:
1 2 3 4 5 6 7 8 9 10 |
mysql> select * from user_info group by age order by mobile; -- 对年龄分组,分组后的结果根据手机号排序 +----+----------+-------------+------+-----+------+ | id | username | mobile | city | age | addr | +----+----------+-------------+------+-----+------+ | 1 | 小明 | 13366668881 | 长沙 | 20 | 衡阳 | | 2 | 小刚 | 13366668882 | 广州 | 21 | 邵阳 | | 4 | 小黑 | 13366668884 | 上海 | 18 | 广州 | | 6 | 小华 | 13366668886 | 长沙 | 30 | 上海 | | 7 | 小李 | 13366668887 | 长沙 | 23 | 北京 | +----+----------+-------------+------+-----+------+ |
要注意的是,分组必须在排序之前,否则会报语法错误:
1 2 |
mysql> select * from user_info order by mobile group by age; 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near "group by age" at line 1 |
三、高级用法
在分组中可以使用max
min
count(*)
等内置函数来对组内数据进行过滤。
例如,根据城市分组,并得到每个城市用户的最大年龄:
1 2 3 4 5 6 7 8 9 |
mysql> select city, max(age) from user_info group by city; +------+----------+ | city | max(age) | +------+----------+ | 上海 | 18 | | 北京 | 20 | | 广州 | 21 | | 长沙 | 30 | +------+----------+ |
利用count(*)
得到分组里的记录条数:
1 2 3 4 5 6 7 8 9 |
mysql> select city, count(*) from user_info group by city; +------+----------+ | city | count(*) | +------+----------+ | 上海 | 1 | | 北京 | 2 | | 广州 | 1 | | 长沙 | 3 | +------+----------+ |
四、总结
分组的功能很强大,用法也很多,可能还有很多复杂的用法都没碰到。
难的其实不是语法,是如何灵活运用,很多时候可以用分组来解决问题,但是根本想不到要去用它。
评论