mysql列转行方法超详细讲解

 更新时间:2023年09月10日 10:06:00   作者:bankq  
mysql行列转换在项目中应用的极其频繁,下面这篇文章主要给大家介绍了关于mysql列转行方法的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下

一、列转行

mysql 数据库中,我们可能遇到将数据库中某一列的数据(多个值,按照英文逗号分隔),转化为多行数据(即一行转多行),然后join关联表,再转化为一行数据

如:有两张表,一用户表,一张学科表,需要查询学科表中的用户姓名

用户表

idusernameage
1zhangsan20
2lisi21
3wamhwu22

学科表

iduser_idssubject
11,2,3数学
22,3语文
31,2英语

我们首先需要把学科表中的user_ids拆分成多行

iduser_idsubject
11数学
12数学
13数学
22语文
23语文
31英语
32英语

二、普通的实现方式(需要依赖 mysql.help_topic 表)

SELECT
    a.id,
    a.subject,
    SUBSTRING_INDEX( SUBSTRING_INDEX( a.`user_ids`, ',', b.help_topic_id + 1 ), ',',-1 ) user_id
FROM
    test a
    JOIN mysql.help_topic b ON b.help_topic_id < ( LENGTH( a.`user_ids`) - LENGTH( REPLACE ( a.`user_ids`, ',', '' ) ) + 1 );

三、mysql.help_topic 无权限处理办法

mysql.help_topic 的作用是对 SUBSTRING_INDEX 函数出来的数据(也就是按照分割符分割出来的)数据连接起来做笛卡尔积。

如果 mysql.help_topic 没有权限,可以自己创建一张临时表,用来与要查询的表连接查询。

获取该字段最多可以分割成为几个字符串:

SELECT MAX(LENGTH(a.`user_ids`) - LENGTH(REPLACE(a.`user_ids`, ',', '' )) + 1) FROM `test` a;

创建临时表,并给临时表添加数据:

注意:

  • 临时表必须有一列从 0 或者 1 开始的自增数据
  • 临时表表名随意,字段可以只有一个
  • 临时表示的数据量必须比 MAX(LENGTH(a.user_ids) - LENGTH(REPLACE(a.user_ids, ',', '' )) + 1) 的值大
DROP TABLE IF EXISTS `tmp_help_topic`;
CREATE TABLE IF NOT EXISTS `tmp_help_topic` (
  `help_topic_id` bigint(20) NOT NULL AUTO_INCREMENT ,
  PRIMARY KEY (`help_topic_id`)
);
INSERT INTO `tmp_help_topic`() VALUES ();
INSERT INTO `tmp_help_topic`() VALUES ();
INSERT INTO `tmp_help_topic`() VALUES ();
INSERT INTO `tmp_help_topic`() VALUES ();
INSERT INTO `tmp_help_topic`() VALUES ();
INSERT INTO `tmp_help_topic`() VALUES ();
INSERT INTO `tmp_help_topic`() VALUES ();
INSERT INTO `tmp_help_topic`() VALUES ();
INSERT INTO `tmp_help_topic`() VALUES ();
INSERT INTO `tmp_help_topic`() VALUES ();

四、查询函数

SELECT
    a.id,a.subject,SUBSTRING_INDEX(SUBSTRING_INDEX(a.`user_ids`, ',', b.help_topic_id), ',',-1 ) user_id
FROM
    test a
    JOIN tmp_help_topic b ON b.help_topic_id <= (LENGTH( a.`user_ids`) - LENGTH(REPLACE(a.`user_ids`, ',', '')) + 1 );

五、join用户表,关联用户名

select 
t2.*,
u.username
from ( 
  SELECT
    a.id,a.subject,SUBSTRING_INDEX(SUBSTRING_INDEX(a.`user_ids`, ',', b.help_topic_id), ',',-1 ) user_id
FROM
    test a
    JOIN tmp_help_topic b ON b.help_topic_id <= (LENGTH( a.`user_ids`) - LENGTH(REPLACE(a.`user_ids`, ',', '')) + 1 ) 
) t2 join user u 
on u.id = t2.user_id
iduser_idsubjectusername
11数学zhangsan
12数学lisi
13数学wangwu
22语文lisi
23语文wangwu
31英语zhangsan
32英语lisi

六、将多行数据转化为一行

select 
t2.*,
group_concat(u.username) username
from ( 
  SELECT
    a.id,a.subject,SUBSTRING_INDEX(SUBSTRING_INDEX(a.`user_ids`, ',', b.help_topic_id), ',',-1 ) user_id
FROM
    test a
    JOIN tmp_help_topic b ON b.help_topic_id <= (LENGTH( a.`user_ids`) - LENGTH(REPLACE(a.`user_ids`, ',', '')) + 1 ) 
) t2 join user u 
on u.id = t2.user_id
group by t2.id
idsubjectuser_idsusername
1数学1,2,3zhangsan,lisi,wangwu
2语文2,3lisi,wangwu
3英语1,2zhangsan,lisi

说明:

  • SUBSTRING_INDEX(SUBSTRING_INDEX(a.user_ids, ',', b.help_topic_id), ',',-1 ) 就是获取 tmp_help_topic 表的 help_topic_id 字段的值作为 name 字段的第几个子串
  • 使用了 join 就会把字段 user_ids 分为 (LENGTH( a.user_ids) - LENGTH(REPLACE(a.user_ids, ',', '')) + 1 ) 行,并且每行的字段刚好是 user_ids字段的第 help_topic_id 个子串

GROUP_CONCAT函数用于将GROUP BY产生的同一个分组中的值连接起来,返回一个字符串结果

GROUP_CONCAT函数首先根据GROUP BY指定的列进行分组,将同一组的列显示出来,并且用分隔符分隔,由函数参数(字段名)决定要返回的列

语法结构

GROUP_CONCAT([DISTINCT] 要连接的字段 [ORDER BY 排序字段 ASC/DESC] [SEPARATOR '分隔符'])

说明:

(1) 使用DISTINCT可以排除重复值

(2) 如果需要对结果中的值进行排序,可以使用ORDER BY子句

(3) SEPARATOR '分隔符'是一个字符串值,默认为逗号

总结

到此这篇关于mysql列转行方法的文章就介绍到这了,更多相关mysql列转行内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • MySQL安装失败的原因及解决步骤

    MySQL安装失败的原因及解决步骤

    因很多同学安装mysql总是出问题,所以下面这篇文章主要给大家介绍了关于MySQL安装失败的原因及解决步骤,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2022-06-06
  • mysql数据库忘记管理员密码的解决方法

    mysql数据库忘记管理员密码的解决方法

    我们在Windows操作系统下编程会使用到MySQL数据库。但是有时,我们会忘记数据库的登录密码?当我们忘记了登录密码,无法进入mysql时,该怎么办呢?这里我们提供mysql的登录秘密的修改
    2018-02-02
  • Mysql自增主键id不是以此逐级递增的处理

    Mysql自增主键id不是以此逐级递增的处理

    这篇文章主要介绍了Mysql自增主键id不是以此逐级递增的处理方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • MySQL中开启和使用通用查询日志的实例教程

    MySQL中开启和使用通用查询日志的实例教程

    这篇文章主要介绍了MySQL中开启和使用通用查询日志的实例教程,包括其备份和关闭等基础操作的例子讲解,需要的朋友可以参考下
    2015-12-12
  • MySQL安装时initializing database失败的问题解决

    MySQL安装时initializing database失败的问题解决

    本文主要介绍了MySQL安装时initializing database失败的问题解决,文中通过图文介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-02-02
  • MySQL数据入库时特殊字符处理详解

    MySQL数据入库时特殊字符处理详解

    本文是对MySQL数据入库时特殊字符的处理进行了详细的介绍,需要的朋友可以过来参考下,希望对大家有所帮助
    2013-11-11
  • MySql深页查询实现方案

    MySql深页查询实现方案

    本文给大家介绍了MySql深页查询实现方案,结合实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧
    2025-11-11
  • MySQL导入与导出备份详解

    MySQL导入与导出备份详解

    大家好,本篇文章主要讲的是MySQL导入与导出备份详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下,方便下次浏览
    2021-12-12
  • mysql5.7使用binlog 恢复数据的方法

    mysql5.7使用binlog 恢复数据的方法

    MySQL的binlog日志是MySQL日志中非常重要的一种日志,记录了数据库所有的DML操作,那么怎样通过binlog 恢复数据,本文就详细的来介绍一下
    2021-06-06
  • Mysql存储过程、触发器、事件调度器使用入门指南

    Mysql存储过程、触发器、事件调度器使用入门指南

    存储过程(Stored Procedure)是一种在数据库中存储复杂程序的数据库对象。为了完成特定功能的SQL语句集,经过编译创建并保存在数据库中,本文给大家介绍Mysql存储过程、触发器、事件调度器使用入门指南,感兴趣的朋友一起看看吧
    2022-01-01

最新评论