mysql分组的探讨
mysql分组的关键字:group by
解释说明:GROUP BY语法可以根据给定数据列的每个成员对查询结果进行分组统计,最终得到一个分组汇总表。SELECT子句中的列名必须为分组列或列函数。
从解释中就可以说明分组的用途是干什么用的。具体统计怎么用后面再说,先看红色标记的后面一句,select子句中的列明必须为分组列或者函数。
测试表:
CREATE TABLE `user_test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) DEFAULT NULL,
`age` int(11) DEFAULT NULL,
`classaNo` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=78 DEFAULT CHARSET=utf8;
测试数据:
1 f 11 001
2 w 12 001
3 z 12 002
4 l 11 002
5 test 0 003
探索:select子句中的列明必须为分组列或者函数
sql1:
select
ut.classaNo
from
user_test ut
group by
ut.classaNo
classaNo
001
002
003
按照要求确实是分组了,通过classaNo,并且列是分组的列。但是如何知道该分组下的具体人员是xx呢?
介绍一个函数:
group_concat()函数:表示的在分组后,将该栏的数据用数组的形式显示在里面。
sql2:
select
ut.classaNo,group_concat(ut.username)
from
user_test ut
group by
ut.classaNo
结果:
classaNo group_concat(ut.username)
001 f,w
002 z,l
003 test
确实是把每个组中的username通过逗号的方式连接起来的。
引出一个问题,列明必须是分组列或者是函数,如果是非分组列会是神马现象?
sql3:
select
ut.classaNo,group_concat(ut.username),username,age
from
user_test ut
group by
ut.classaNo
结果:
classaNo group_concat(ut.username) username age
001 f,w f 11
002 z,l z 12
003 test test 0
根据结果所示,若是非分组列,该列的值则是第一行显示的数据的列。
探索:结合group by使用的函数
1.count(*) 统计该分组有多少条记录
2.sum(*) 该组某个列求和
3.max(*) 求出该组中某列最大的值
4.min(*) 求出该组中最小的值
5.avg(*) 求出该组的平均值
ps:group by 分组之后添加条件,后面条件也必须是函数
例如:
sql4:
查询分组后的username至少有2个组
select
ut.classaNo,group_concat(ut.username),count(ut.username)
from
user_test ut
group by
ut.classaNo
having
count(ut.username) >= 2
实际项目中案例sql5求出分组中最大的一条记录值,数据库表结构如下:
-- Table "studycase_student_grade" DDL
CREATE TABLE `studycase_student_grade` (
`id` varchar(32) NOT NULL DEFAULT '' COMMENT 'ID',
`schoolId` int(4) NOT NULL COMMENT '校区编码',
`classCode` varchar(100) NOT NULL COMMENT '班级号',
`className` varchar(100) NOT NULL COMMENT '班级名称',
`courseCode` varchar(200) DEFAULT NULL COMMENT '课程编号',
`teacherEmail` varchar(100) NOT NULL COMMENT '教师邮箱',
`teacherName` varchar(100) NOT NULL COMMENT '教师姓名',
`lessonNo` int(4) NOT NULL COMMENT '课次',
`lessonTime` varchar(50) NOT NULL COMMENT '上课时间',
`studentNo` varchar(100) NOT NULL COMMENT '学员号',
`studentName` varchar(100) NOT NULL COMMENT '学生姓名',
`gradeType` int(4) DEFAULT NULL COMMENT '成绩类型',
`fullMarks` int(4) DEFAULT NULL COMMENT '满分',
`realGrade` int(4) NOT NULL COMMENT '真实成绩',
`invalid` smallint(2) NOT NULL COMMENT '是否有效1-有效,0-无效',
`createTime` datetime NOT NULL,
`updateTime` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='学习情况-学生成绩表';
要求:按班级分组,创建时间进行排序,一般group by分组得道的记录都是第一条的,如何取出最大的时间所在的记录,在进行排序了?
思路:
a.求分组后createTime max最大的记录
(select temp.classCode, max(temp.createTime) createTime from studycase_student_grade temp where temp.teacherEmail = 'mytest'
and temp.invalid = 1 group by temp.classCode) t
b.原来的表中找到刚才得道最大记录的表的记录,在根据order by进行排序
select
ssg.schoolId, ssg.classCode, ssg.className, ssg.teacherEmail,ssg.teacherName,ssg.studentName,ssg.createTime
from
studycase_student_grade ssg
inner join
(select temp.classCode, max(temp.createTime) createTime from studycase_student_grade temp where temp.teacherEmail
= 'mytest' and temp.invalid = 1 group by temp.classCode) t
on
ssg.classCode = t.classCode
and
ssg.createTime = t.createTime
and
ssg.teacherEmail = 'mytest'
and
ssg.invalid = 1
order by
ssg.createTime desc
总结:
a.group by 分组后不能添加非分组列,若添加,则分分组列的值为分组后的第一个列的数值
b.group by 分组通常和函数结合使用作为计算,可以有过滤条件,条件判断也是通过函数。