MySQL中的GROUP_CAT()函数和ORDER BY排序

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()函数是将一组值连接成字符串
*/

关于该题的具体信息和相关的表网上可以查找到,这里只是引用说明。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值