mysql使用逗号分隔的一行数据转多行数据

文章目录

  • 学习链接
  • 准备
    • 建表
    • 插入数据
  • 方法
    • MySQL逗号拼接的列拆分为多行(不使用mysql.help_topic)
    • 遇到字段以逗号分隔符分号分隔符存放多个值,需要一行转化多行,以用来关联(使用mysql.help_topic)
      • 改为LEFT JOIN后的效果
      • 封装为函数
      • 原理简析
      • SUBSTRING_INDEX(str, delim, count)
      • replace( str, from_str, to_str)
      • LENGTH( str )
    • 将逗号分割的字段内容转换为多行并group by
      • 1、原来的字段格式
      • 2、将逗号分割的字段内容转换为多行
      • 3、对以上结果进行分组

学习链接

MYSQL: sql中某一个字段内容为用逗号分割的字符串转换成多条数据(适用于部分树机构)

MySQL逗号拼接的列拆分为多行(不使用mysql.help_topic)

遇到字段以逗号分隔符分号分隔符存放多个值,需要一行转化多行,以用来关联(使用mysql.help_topic)

【mysql】将逗号分割的字段内容转换为多行并group by

Mysql 行转列,把逗号分隔的字段拆分成多行(这个也还可以)

【mysql】将逗号分割的字段内容转换为多行并group by(这个讲的很详细)

MySql字符串拆分实现split功能(字段分割转列、转行)(很nice)

MySql逗号拼接的列拆分为多行(nice)

PostgreSQL 字符串分隔函数(regexp_split_to_table)介绍以及示例应用

准备

建表

CREATE TABLE `u_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  `hobbies` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8;

插入数据

INSERT INTO `test`.`u_user` (`id`, `name`, `hobbies`) VALUES (1, 'zj', 'ps,blender,java');
INSERT INTO `test`.`u_user` (`id`, `name`, `hobbies`) VALUES (2, 'ls', 'u8,u9,pmp,cpa');
INSERT INTO `test`.`u_user` (`id`, `name`, `hobbies`) VALUES (3, 'zzhua', 'spring');
INSERT INTO `test`.`u_user` (`id`, `name`, `hobbies`) VALUES (4, 'zengjian', NULL);
INSERT INTO `test`.`u_user` (`id`, `name`, `hobbies`) VALUES (5, 'halo', '');
INSERT INTO `test`.`u_user` (`id`, `name`, `hobbies`) VALUES (6, 'netty', 'a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z');

-- truncate table u_user;

插入数据如下图所示,有多个的使用逗号分隔的,有单个未使用逗号的,有nul的,有空字符的,有特别多个的。
在这里插入图片描述

方法

MySQL逗号拼接的列拆分为多行(不使用mysql.help_topic)

SELECT
	id,
	name,
	SUBSTRING_INDEX( SUBSTRING_INDEX( hobbies, ',', n ), ',', - 1 ) AS split 
FROM
	`u_user`,
	( SELECT @rownum := @rownum + 1 AS n FROM ( SELECT @rownum := 0 ) r, `u_user` ) x 
WHERE
	1 = 1 
	AND n <= ( LENGTH( hobbies ) - LENGTH( REPLACE ( hobbies, ',', '' ) ) + 1 ) 
ORDER BY
	id

在这里插入图片描述
从查询结果来看,这个方法有几个缺点:1、不按顺序来(如果顺序没有特定含义的话,可以忽略),2、会忽略null的数据 3、netty所在的那1条数据,只拆分出了前面6个(这个问题比较严重,这个6经过测试是原表数据的总条数。假设原表中只有2条数据,那么netty所在的那条数据就只会拆分出前2条数据)

遇到字段以逗号分隔符分号分隔符存放多个值,需要一行转化多行,以用来关联(使用mysql.help_topic)

原文链接:https://blog.csdn.net/qq_35124072/article/details/124716478

SELECT
	u.id, 
	u.name, 
	SUBSTRING_INDEX( SUBSTRING_INDEX( u.`hobbies`, ',', b.help_topic_id + 1 ), ',', -1 ) AS REGEXP_COUNT_COL 
FROM
	u_user u
	INNER JOIN mysql.help_topic b ON b.help_topic_id < (
		LENGTH( u.`hobbies` ) - LENGTH( REPLACE(u.`hobbies`,',','') )  +  1  -- hobbies的长度 - hobbies去掉所有逗号的长度 + 1
	)

在这里插入图片描述
从查询结果来看,1、保留了原来的顺序,2、忽略了null的数据(可以将INNER JOIN改成LEFT JOIN即可),3、netty那一条比较多的数据保留了下来,4、感觉就是上一种方法的变体,就是借助了mysql.topic表的从0开始递增的id字段,这个表中在当前5.17.7版本中有637条数据。5、其实可以不用借助mysql.topic这张表,但是我们就需要自建这样的一张表了,或者我们手动select 1 union select 2 union…这样拼着来使用

改为LEFT JOIN后的效果

在这里插入图片描述

封装为函数

可以参照上面将待分隔的数据作为参数传入,并可封装为函数使用,如下:
在这里插入图片描述

原理简析

1、mysql.help_topic表的help_topic_id 字段是从0开始的自增的int类型的值,所以当部分用户访问该表被拒绝的时候,可以自己建一张临时辅助表,id的值建议至少从0到100,保存100列(取决于参数中可能出现多少个分隔符);
2、如果是别的分隔符,把sql中的’;'替换成其他就好
3、sql原理:大概就是利用参数中分隔符出现的次数来重复连接,以多次返回值,每次返回值都利用SUBSTRING_INDEX截取不同位置的值,达到拆分到多行的目的。

SUBSTRING_INDEX(str, delim, count)

  • str 需要拆分的字符串
  • delim 分隔符,通过某字符进行拆分
  • count 当 count 为正数,取第 n 个分隔符之前的所有字符; 当 count 为负数,取倒数第 n 个分隔符之后的所有字符
-- 得到的结果: 7654,7698
SUBSTRING_INDEX('7654,7698,7782,7788',',',2) 

-- 得到的结果: 7782,7788
SUBSTRING_INDEX('7654,7698,7782,7788',',',-2)

replace( str, from_str, to_str)

  • str 需要进行替换的字符串
  • from_str 需要被替换的字符串
  • to_str 需要替换的字符串
-- 得到的结果: 7654769877827788
REPLACE('7654,7698,7782,7788',',','')

LENGTH( str )

  • str 需要计算长度的字符串
-- 得到的结果: 19
LENGTH('7654,7698,7782,7788')

将逗号分割的字段内容转换为多行并group by

1、原来的字段格式

在这里插入图片描述

2、将逗号分割的字段内容转换为多行

下面直接给出sql,并对sql的每一步做出解释,更有助于大家理解

首先要说明的是,mysql.help_topic本身是mysql的一张信息表,用来存储各种注释等帮助信息,help_topic拥有一个自增为1的id属性–help_topic_id ,并且可以当做下标来使用,拥有固定数量的数据
解释:

  1. length(a.attendee_uid) - length(REPLACE(a.attendee_uid, ‘,’, ‘’)) + 1
  2. 第一步的意思是 字段attendee_uid的长度 - 字段attendee_uid去除掉逗号的长度,然后再+1就得到了通过逗号分割后有几条数据
  3. 比如上一步得到是3 那就可以确定这个字段要拆分为3行 help_topic_id<3 也就是可以得到下标 0,1,2
  4. 比如这条数据’zhangsan,lisi,wangwu’ 第一个substring_index的意思就是把’zhangsan,lisi,wangwu’通过逗号分割,然后取b.help_topic_id + 1(help_topic_id就是第3步得到的下标)结果就是zhangsan
  5. 第二个substring_index的意思是 再从第4步的结果 从右边取第一个, 因为’zhangsan,lisi,wangwu’如果获取到下标为2的话那得到的就是’zhangsan,lisi’ 所以再从右边取第一个就得到了 ‘lisi’
SELECT 
	a.id '会议id', 
	a.attendee_uid '原始参会人列表', 
	# 4、比如这条数据'zhangsan,lisi,wangwu'  第一个substring_index的意思就是把'zhangsan,lisi,wangwu'通过逗号分割,
	#    然后取b.help_topic_id + 1(help_topic_id就是第3步得到的下标)结果就是zhangsan
	# 5 第二个substring_index的意思是 再从第4步的结果 从右边取第一个, 因为'zhangsan,lisi,wangwu'如果获取到下标为2的话那得到的就是'zhangsan,lisi'  所以再从右边取第一个就得到了 'lisi'
	substring_index(substring_index(a.attendee_uid, ',', b.help_topic_id + 1), ',', -1) AS '分割后的参会人账号' 
FROM `fusion_meeting` a 
JOIN mysql.help_topic b 
# 1、length(a.attendee_uid) - length(REPLACE(a.attendee_uid, ',', '')) + 1 
# 2、这个的意思是 字段attendee_uid的长度 - 字段attendee_uid去除掉逗号的长度,然后再+1就得到了通过逗号分割后有几条数据
# 3、比如上一步得到是3  那就可以确定这个字段要拆分为3行 help_topic_id<3 也就是可以得到下标 0,1,2
ON b.help_topic_id < length(a.attendee_uid) - length(REPLACE(a.attendee_uid, ',', '')) + 1
WHERE a.hw_conf_id = '969471016';

结果:
在这里插入图片描述

3、对以上结果进行分组

SELECT uid as '参会人账号',COUNT(*) '参会次数' FROM (
	SELECT 
		a.id '会议id', 
		a.attendee_uid '原始参会人列表', 
		substring_index(substring_index(a.attendee_uid, ',', b.help_topic_id + 1), ',', -1) AS uid 
	FROM `fusion_meeting` a 
	JOIN mysql.help_topic b 
		 ON b.help_topic_id < length(a.attendee_uid) - length(REPLACE(a.attendee_uid, ',', '')) + 1
	WHERE a.hw_conf_id = '969471016'

) c GROUP BY c.uid;

结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/548095.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

git 上传代码到 github

准备工作 git Git LFS&#xff08;大文件>100Mb&#xff09; git 参考手册 github 建立仓库&#xff1a;New repository git 指令 git add . 用于将当前目录下的所有文件添加到 Git 仓库的暂存区中。 git add . 命令会将当前目录下的所有文件添加到 Git 仓库的暂存区中…

五、流程控制之循环

目录 5.1 步进循环语句for 5.1.1 带列表的for循环语句 5.1.2 不带列表的for循环语句 5.1.3 类C风格的for循环语句 5.2 while循环语句 5.2.1 while循环读取文件 5.2.2 while循环语句示例 5.3 until循环语句 5.4 select循环语句 5.5 嵌套循环 5.1 步进循环语句for for…

如何使用ArcGIS Pro进行路径分析

路径分析是一种空间分析技术&#xff0c;用于确定两个或多个地点之间最佳路径或最短路径&#xff0c;这里为大家介绍一下在ArcGIS Pro中如何进行路径分析&#xff0c;希望能对你有所帮助。 数据来源 教程所使用的数据是从水经微图中下载的道路数据&#xff0c;除了道路数据&a…

大厂面试:获取字符串的全排列

一、概念 现有一个字符串&#xff0c;要打印出该字符串中字符的全排列。例如输入字符串abc&#xff0c;则打印出由字符a、b、c所能排列出来的所有字符串abc、acb、bac、bca、cab和cba。 可以基于回溯法来解决这个问题。 二、代码 public class Permutation {//输出字符串str的全…

【自媒体创作利器】AI白日梦+ChatGPT 三分钟生成爆款短视频

AI白日梦https://brmgo.com/signup?codey5no6idev 引言 随着人工智能&#xff08;AI&#xff09;技术的快速发展&#xff0c;AI在各个领域都展现出了强大的应用潜力。其中&#xff0c;自然语言处理技术的进步使得智能对话系统得以实现&#xff0c;而ChatGPT作为其中的代表之一…

【Linux】磁盘阵列RAID技术

目录 一、RAID介绍 1.1 什么是RAID技术&#xff1f; 1.2 为什么要使用RAID技术&#xff1f; 二、RAID级别 2.1 常见的RAID级别 2.2 常见RAID介绍 三、RAID特性对比 一、RAID介绍 1.1 什么是RAID技术&#xff1f; 把多块独立的物理磁盘按不同的方式组合起来形成一个硬盘…

人工智能讲师大模型培训老师叶梓:基于大型语言模型的自主智能体:架构设计与应用前景

在人工智能的快速发展中&#xff0c;大型语言模型&#xff08;LLM&#xff09;已成为推动技术进步的关键力量。LLM的出现不仅改变了我们与机器的交互方式&#xff0c;也为构建具有高级认知能力的自主智能体&#xff08;AI Agent&#xff09;提供了新的可能性。本文旨在探讨基于…

(非技术) 基因遗传相关知识学习笔记

目录 一、基因遗传名词解释 二、什么叫显性遗传和隐性遗传&#xff1f; 三、如何确定遗传性质呢&#xff1f;是显性还是隐性&#xff1f; 四、常规例子1&#xff1a; 五、常规例子2&#xff1a; 六、实际案例&#xff1a; 七、思考题&#xff1a; 八、参考&#xff1a; …

云计算: OVN 集群 部署分布式交换机

目录 一、实验 1.环境 2.OVN 集群 部署云主机 3.中心端添加DVS分布式大二层交换机 二、问题 1.南向控制器查看主机名只显示localhost 2.中心端如何添加DVR分布式⼤三层路由器 一、实验 1.环境 (1) 主机 表1 宿主机 主机架构软件主要服务IP备注ovn_central中心端 ovn…

【Linux】基础I/O>文件系统软硬链接动静态库详解

主页&#xff1a;醋溜马桶圈-CSDN博客 专栏&#xff1a;Linux_醋溜马桶圈的博客-CSDN博客 gitee&#xff1a;mnxcc (mnxcc) - Gitee.com 目录 1.C语言文件接口 1.1 hello.c写文件 1.2 hello.c读文件 1.3 输出信息到显示器 1.4 stdin & stdout & stderr 1.5 总结打…

Android Framework学习笔记(3)----Binder

什么是Binder&#xff1f; Binder是linux IPC机制的其中一种。它贯穿于应用层&#xff0c;framework层&#xff0c;以及linux Core层。 什么是IPC? 跨进程通信&#xff0c; InterProcess Communication. IPC机制都有哪些&#xff1f; 通道信号量消息队列BinderSocket共享内…

从IPv4到IPv6:解密网络通信的新时代

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 从IPv4到IPv6&#xff1a;解密网络通信的新时代 前言ipv4介绍ipv6介绍IPv4与IPv6的区别IPv4地址枯竭问题和IPv6的解决方案 ipv6的优势IPv6在新兴技术领域的应用 ipv4向ipv6的过渡挑战解决方案IPv6部署…

NVIDIA全系列GPU技术路线演进分析

NVIDIA GPU 架构梳理 近期深入研究并行计算,需探究底层硬件精髓。高性能计算界,英伟达显卡稳居霸主地位。本文旨在梳理NVIDIA GPU架构之演进历程,助您洞悉其技术脉络,把握未来计算趋势。 目录: NVIDIA GPU架构历经数次革新:从Tesla架构奠定基石,到Fermi架构提升性能,再…

【JAVA基础篇教学】第十五篇:Java中Spring详解说明

博主打算从0-1讲解下java基础教学&#xff0c;今天教学第十五篇&#xff1a;Java中Spring详解说明。 Spring 框架是一个广泛应用于 Java 开发的轻量级、全栈式的企业应用开发框架&#xff0c;它提供了众多功能强大的模块&#xff0c;用于简化企业级应用程序的开发。下面详细说…

MySQL慢查询日志配置指南:发现性能瓶颈,提升数据库效率

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 MySQL慢查询日志配置指南&#xff1a;发现性能瓶颈&#xff0c;提升数据库效率 前言慢查询日志介绍配置慢查询日志配置慢查询日志失效日志格式与记录内容高级配置与注意事项配置过程中的注意事项&…

【python】flask操作数据库工具SQLAlchemy,详细用法和应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

EasyRecovery激活秘钥2024最好用的电脑数据恢复软件下载

EasyRecovery数据恢复软件是一款专业且功能强大的数据恢复工具&#xff0c;它旨在帮助用户从各种存储设备中恢复由于各种原因&#xff08;如误删除、格式化、病毒攻击、系统崩溃等&#xff09;导致丢失的数据。这款软件支持多种存储介质&#xff0c;包括但不限于硬盘驱动器、U盘…

白盒测试之路径覆盖与基本路径覆盖

白盒测试之路径覆盖与基本路径覆盖&#xff08;蓝桥课学习笔记&#xff09; 1、路径覆盖 实验介绍 程序中的路径是执行程序时经过的分支的集合。路径覆盖法是指设计一定数量的测试用例运行被测程序&#xff0c;使程序中的所有路径都至少被执行一次。路径覆盖率的计算方法为&a…

web前端js笔记

1&#xff0c;对象 let{ 属性 方法 } 2&#xff0c;闭包 只有函数内部的子函数才能读取局部变量&#xff0c;所以闭包可以理解成定义在一个函数内部的函数&#xff0c;在本质上&#xff0c;闭包是将函数内部和函数外部连接起来的桥梁。 3&#xff0c;math console.log(Math.flo…

✌粤嵌—2024/4/15—汇总区间

代码实现&#xff1a; /*** Note: The returned array must be malloced, assume caller calls free().*/ char** summaryRanges(int* nums, int numsSize, int *returnSize) {char **res malloc(sizeof(char*) * numsSize);*returnSize 0;int i, j;for (i 0; i < numsSi…