【mysql】逗号分割字段的行列转换

  由于很多业务表因为历史原因或者性能原因,都使用了违反第一范式的设计模式,即同一个列中存储了多个属性值。这种模式下,应用常常需要将这个列依据分隔符进行分割,并得到列转行的结果:这里使用substring_index函数进行处理

建表语句:

复制代码
 1 DROP table if EXISTS tbl_name;
 2 CREATE TABLE tbl_name(
 3     id       int(11)    not null auto_increment,
 4     userName varchar(100)    not null,
 5 PRIMARY KEY(id)
 6 )
 7 ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
 8 
 9 insert into tbl_name values (1,'a,aa,aaa');
10 insert into tbl_name values (2,'b,bb');
11 insert into tbl_name values (3,'c,cc');
复制代码

如下图:

sql语句:

1 SELECT a.id,SUBSTRING_INDEX(SUBSTRING_INDEX(a.userName,',',b.help_topic_id+1),',',-1) as name  
2 from tbl_name a left join mysql.help_topic b 
3 on b.help_topic_id < (LENGTH(a.userName)-LENGTH(REPLACE(a.userName,',',''))+1) 
4 ORDER BY a.id;

执行结果:

分析如下:

LENGTH(a.userName)-LENGTH(REPLACE(a.userName,',',''))+1

表示了按逗号分割后,获得行转成列的数量,以下简称n;

复制代码
根据id进行循环

{
  判断:i 是否 <= n
    {
      获取最靠近第 i 个逗号之前的数据, 即 SUBSTRING_INDEX(SUBSTRING_INDEX(a.userName,',',b.help_topic_id+1),',',-1)
      i = i +1 
    }
  id = id +1 
}
复制代码

总结:

这种方法的缺点在于,我们需要一个拥有连续数列的独立表。并且连续数列的最大值一定要大于符合分割的值的个数。当然,mysql内部也有现成的连续数列表可用。如mysql.help_topic: help_topic_id 共有504个数值,一般能满足于大部分需求了。

posted @   howtosay  阅读(15838)  评论(1编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示