前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL方法GROUP_CONCAT的应用

MySQL方法GROUP_CONCAT的应用

作者头像
IT小马哥
发布2022-09-23 11:26:00
6780
发布2022-09-23 11:26:00
举报
文章被收录于专栏:Java Tale

MySQL方法GROUP_CONCAT的应用,多对多联表查询,以A表为主表,通过关联表C查询出B表关联A表任意记录的多条记录的某个字段的合并值

开发中遇到这样的一个需求:用户表为A,角色表为B,用户角色关系通过C表多对多关联,我们需要查询出每一个用户所拥有的角色,以下图的格式显示:

用户ID

用户姓名

拥有角色

1

小明1

角色1,角色4,角色5,角色6...

2

小明2

角色1,角色4,角色5,角色6...

代码语言:javascript
复制
-- 用户表
CREATE TABLE `sys_user` (
  `user_id` int NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `user_name` varchar(50) NOT NULL COMMENT '用户姓名',
  `user_age` varchar(3) DEFAULT NULL COMMENT '用户年龄',
  `creater` varchar(255) DEFAULT NULL COMMENT '创建人',
  `create_time` datetime DEFAULT NULL COMMENT '创建时间',
  `updater` varchar(50) DEFAULT NULL COMMENT '更新人',
  `update_time` datetime DEFAULT NULL COMMENT '更新时间',
  PRIMARY KEY (`user_id`)
)  ENGINE=InnoDB AUTO_INCREMENT=1  COMMENT='用户表';

-- 角色表
CREATE TABLE  `sys_role`  (
  `role_id` int NOT NULL AUTO_INCREMENT COMMENT '角色ID',
  `role_name` varchar(50) NOT NULL COMMENT '角色名称',
  `creater` varchar(50) NULL COMMENT '创建人',
  `create_time` datetime NULL COMMENT '创建时间',
	`updater` varchar(50) NULL COMMENT '更新人',
  `update_time` datetime NULL COMMENT '更新时间',
  PRIMARY KEY (`role_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1    COMMENT='角色表';

-- 用户角色关系表
CREATE TABLE  `sys_user_role`  (
  `user_role_id` int NOT NULL AUTO_INCREMENT COMMENT '用户角色关系ID',
  `role_id` varchar(50) NOT NULL COMMENT '角色ID',
	`user_id` varchar(50) NOT NULL COMMENT '用户ID',
  PRIMARY KEY (`user_role_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1   COMMENT='用户角色关系表';

-- 插入模拟数据 start
create procedure insert8()
begin declare i int default 0; 
repeat 
INSERT INTO sys_role(role_name,creater,create_time,updater,update_time)select role_name,   creater, create_time, updater,update_time from sys_role UNION ALL select '角色','1',NOW(),'1', NOW() from dual ;
INSERT INTO sys_user(user_name,user_age,creater,create_time,updater,update_time) select  user_name,user_age,creater,create_time, updater,update_time from sys_user UNION ALL select '小明','10','1',NOW(),'1',NOW() from dual ;
set i=i+1;
until i>8 end repeat;  end;
call insert8; 
drop procedure if exists insert8;
 

INSERT INTO  sys_user_role (role_id, user_id ) 
select   role_id, user_id from sys_role
INNER JOIN sys_user ;

update sys_user set user_name=REPLACE(user_name,user_name,CONCAT( user_name,user_id) );
update sys_role set role_name=REPLACE(role_name,role_name,CONCAT(role_name,role_id) );
-- 插入模拟数据 end

-- 测试完毕删除数据
drop table sys_user;
drop table sys_role;
drop table sys_user_role;

在解决问题中发现了两种方式可实现该功能

方式一

代码语言:javascript
复制
 SELECT su.user_id AS userId,su.user_name AS userName,
    (
        SELECT  GROUP_CONCAT(sr.role_name)
        FROM sys_user_role sur
        LEFT JOIN sys_role sr ON sr.role_id = sur.role_id
        WHERE sur.user_id = su.user_id
    ) AS roleNames
FROM sys_user su   
ORDER BY  su.user_id

方式一是把查询c表作为主表,并且left join B表的一个子查询,查出每一个用户id拥有的角色名称拼接结果作为拥有角色字段值的,我们看看其查询性能

代码语言:javascript
复制
查询时间:56.088s   共511条

可见查询22条左右数据需要4秒多,这种速度我们显然是不能接受的,而且需要以拥有小区的名称做模糊查询时候也无从下手。于是后来继续想办法优化,就找到了下面的方式二。

方式二

代码语言:javascript
复制
SELECT su.user_id AS userId, su.user_name AS userName,temp.roleNames
FROM sys_user su
LEFT JOIN (
    SELECT sur.user_id, GROUP_CONCAT(sur.role_id) AS roleIds,
        GROUP_CONCAT(sr.role_name) AS roleNames
    FROM sys_user_role sur
 				LEFT JOIN sys_role sr ON sr.role_id = sur.role_id
    GROUP BY sur.user_id
) temp ON temp.user_id = su.user_id ORDER BY  su.user_id

方式二依然有一个查询用户拥有小区名称拼接结果的子查询,只是这个子查询不是直接作为结果字段返回,而是根据用户id为group规则查询出来每一个用户的拥有小区结果字符串,然后作为A表的left join的虚拟表,下面看一下测试结果

代码语言:javascript
复制
查询时间:0.657s   共511条

可见同样查询一万条数据一秒钟都不用,查询速度提高了至少20倍,而且因为是虚拟关联表,可以直接用 temp.roleNames like'%角色1%' 而实现模糊查询。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-08-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 方式一
  • 方式二
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档