GROUP_CONCAT()函数:该函数返回带有来自一个组的连接的非NULL值的字符串结果,同一般同group by一起使用。
如图,有这么一张表:
GROUP_CONCAT()函数可以将一个组的值连接成字符串,如下:
但GROUP_CONCAT()函数一般同GROUP BY分组语句一起使用,比如上面的表就可以按照snum分为多个组,如下:
可以发现把同一组的cnum字段都连接成一个字符串了。但我们遇到一个问题,发现'01'、'02'和'03'是同一组的,如果按照升序或者降序,那么前四个的字符串应该相同,但遗憾的是四个字符串并不相同,所以我们想到了排序来解决这个问题,如下:
发现变成了这样,只是字符串排序,并不是'01'、'02'和'03'进行排序,也就是说order by排序失效了,这是为什么呢?
这是由于执行顺序不同造成的,在DQL语言中,order by是最后第二个执行的(最后一个执行的是limit);我们第一条sql中首先执行了group_concat函数,执行之后只有一条结果,所以无论怎么order by都是一样的。
那么解决方法是可以将order by写在group_concat函数中,就能解决order by失效的问题。
这就达成我们想要的效果了,所以使用语法就是
SELECT GROUP_CONCAT(字段名1 ORDER BY 字段名1 DESC|ASC)
FROM 表名 GROUP BY 字段名2;
该函数一个典型应用就是:查询和"01"号的同学学习的课程完全相同的其他同学的信息
-- 4.13查询和"01"号的同学学习的课程完全相同的其他同学的信息
SELECT student.*,GROUP_CONCAT(sc.cnum ORDER BY sc.cnum DESC) personal_courses
FROM sc
INNER JOIN student
ON sc.snum=student.snum
WHERE student.snum!='01'
GROUP BY sc.snum
having personal_courses=(
SELECT GROUP_CONCAT(cnum ORDER BY cnum DESC)
FROM sc
WHERE snum='01'
)
/*
解题思路:
第一步:查询学号为"01"的同学所选的课程编号列表
SELECT cnum FROM sc WHERE snum='01';
第二步:但是每个同学按学生编号分组后查询到的选课记录是一个列表,而学号为'01'的同学所选的课程编号也是一个列表,
那么该如何去比较呢?这里提出了一个思路:将列表中的值拼接成字符串,然后比较两个字符串是否相等,因为
这毕竟不是编程语言,可以循环进行比较,但需要考虑到GROUP_CONCAT()函数拼接成字符串后里面的顺序不一定
是我们想要的,所以需要在拼接字符串之前先排序,但使用order by cnum desc是失效的,因为执行顺序不同,
所以要将排序放到GROUP_CONCAT()函数中,这个是GROUP_CONCAT()函数语法所允许的,因此SQL语句变成了如下:
SELECT GROUP_CONCAT(cnum ORDER BY cnum DESC) FROM sc WHERE snum='01';
第三步:将每个铜须按学生编号进行分组,并用GROUP_CONCAT()函数将该组的值排序后再拼接成字符串
SELECT GROUP_CONCAT(sc.cnum ORDER BY sc.cnum DESC) personal_courses FROM sc GROUP BY sc.snum
第四步:将第三步的结果集中的每一个字符串与第二步结果比较
SELECT GROUP_CONCAT(sc.cnum ORDER BY sc.cnum DESC) personal_courses FROM sc GROUP BY sc.snum HAVING personal_courses=(第二步结果)
第五步:需要排除比较的'01'同学,这是在分组前的筛选,所以使用where
SELECT GROUP_CONCAT(sc.cnum ORDER BY sc.cnum DESC) personal_courses FROM sc WHERE student.snum!='01' GROUP BY sc.snum HAVING personal_courses=(第二步结果)
第六步:就是关联student表,查询学生详细信息,使用内连接即可
特别注意:
不能用数量相等去判断,加如'01'号同学选修了'语文'和'数学',但'02'同学选修了'英语'和'化学',虽然他们数量相等,但不是相同的课程
为什么需要排序:因为可能GROUP_CONCAT()函数连接成的字符串是'01,02,03'和'03,02,01',它们是相等的,但字符串却不相等
GROUP_CONCAT()函数是将一组值连接成字符串
*/
关于该题的具体信息和相关的表网上可以查找到,这里只是引用说明。