行列转换常见场景

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

表数据:

ID Value
1 tiny,small,big
2 small,medium
3 tiny,big

期望得到结果:

ID Value
1 tiny
1 small
1 big
2 small
2 medium
3 tiny
3 big

具体方法

先从一个具体实例开始我们的介绍:

#准备示例数据
create table tbl_name (ID int ,mSize varchar(100));
insert into tbl_name values (1,'tiny,small,big');
insert into tbl_name values (2,'small,medium');
insert into tbl_name values (3,'tiny,big');

#用于行列转换循环的自增表
create table incre_table (AutoIncreID int);
insert into incre_table values (1);
insert into incre_table values (2);
insert into incre_table values (3);

#实现行列转换的SQL
select a.ID,substring_index(substring_index(a.mSize,',',b.AutoIncreID),',',-1)
from
tbl_name a
join
incre_table b
on b.AutoIncreID <= (length(a.mSize) - length(replace(a.mSize,',',''))+1)
order by a.ID;

原理分析: 这个join最基本原理是笛卡尔积。通过这个方式来实现循环。 以下是具体问题分析:length(a.Size) - length(replace(a.mSize,',',''))+1 表示了,按照逗号分割后,改列拥有的数值数量,下面简称n join过程的伪代码:

根据ID进行循环
{
    判断:i 是否 <= n
    {
        获取最靠近第 i 个逗号之前的数据, 即 substring_index(substring_index(a.mSize,',',b.ID),',',-1)
        i = i +1
    }
    ID = ID +1
}

改进版本

上面一种方法方法的缺点在于,我们需要一个拥有连续数列的独立表(也就是上文中的incre_table)。并且连续数列的最大值一定要大于符合分割的值的个数。 例如有一行的mSize 有100个逗号分割的值,那么我们的incre_table 就需要有至少100个连续行。 当然,mysql内部也有现成的连续数列表可用。如mysql.help_topic, help_topic_id 共有504个数值,一般能满足于大部分需求了。

改写后如下:

select a.ID,substring_index(substring_index(a.mSize,',',b.help_topic_id+1),',',-1)
from
tbl_name a
join
mysql.help_topic b
on b.help_topic_id < (length(a.mSize) - length(replace(a.mSize,',',''))+1)
order by a.ID;

转 http://cenalulu.github.io/mysql/column-row-reverse/

MySQL中行列转换的SQL技巧的更多相关文章

  1. SQL Server中行列转换 Pivot UnPivot

    SQL Server中行列转换 Pivot UnPivot PIVOT用于将列值旋转为列名(即行转列),在SQL Server 2000可以用聚合函数配合CASE语句实现 PIVOT的一般语法是:PI ...

  2. 如何查找MySQL中查询慢的SQL语句

    如何查找MySQL中查询慢的SQL语句 更多 如何在mysql查找效率慢的SQL语句呢?这可能是困然很多人的一个问题,MySQL通过慢查询日志定位那些执行效率较低的SQL 语句,用--log-slow ...

  3. Mysql中 查询慢的 Sql语句的记录查找

    Mysql中 查询慢的 Sql语句的记录查找 慢查询日志 slow_query_log,是用来记录查询比较慢的sql语句,通过查询日志来查找哪条sql语句比较慢,这样可以对比较慢的sql可以进行优化. ...

  4. 简单的叙述下SQL中行列转换的小知识!

    行列转换对于工作还是学习中总是不可避免的会遇到(虽然本人还尚未工作,萌萌哒的学生一枚),解决的方法也有很多,我这里就总结一下我所想解决的问题以及怎么去解决的方法, 可能网上已经有很多类似的方法了,有的 ...

  5. MySQL基础操作&&常用的SQL技巧&&SQL语句优化

    基础操作     一:MySQL基础操作         1:MySQL表复制             复制表结构 + 复制表数据             create table t3 like t ...

  6. Mysql实现行列转换

    前言: 最近又玩起了sql语句,想着想着便给自己出了一道题目:“行列转换”.起初瞎折腾了不少时间也上网参考了一些博文,不过大多数是采用oracle数据库当中的一些便捷函数进行处理,比如”pivot”. ...

  7. 如何查找MySQL中查询慢的SQL语句(转载)

    转载自https://www.cnblogs.com/qmfsun/p/4844472.html 如何在mysql查找效率慢的SQL语句呢?这可能是困然很多人的一个问题,MySQL通过慢查询日志定位那 ...

  8. MySQL中JSON字段的使用技巧

    mysql5.7.8之后开始原生支持json. 在类似mongodb这种nosql数据库中,json存储数据是非常自然的, 在mysql中合理的使用json,能够带来极大的便利 Json字段的使用场景 ...

  9. MySQL中的find_in_set()函数使用技巧心得与应用场景总结

    Author:极客小俊 一个专注于web技术的80后 我不用拼过聪明人,我只需要拼过那些懒人 我就一定会超越大部分人! CSDN@极客小俊,CSDN官方首发原创文章 企业博客 CSDN.com 个人博 ...

随机推荐

  1. c规范(2)

    一:对齐 1 程序的分界符' {'和' }'应独占一行并且位于同一列,同时与引用它们的语句左对齐. 2  { }之内的代码块在' {'右边数格处左对齐. 二:注释 注释通常用于:( 1)版本.版权声明 ...

  2. Android IPC(inter-process Communitcation)

    Android IPC(inter-process Communitcation) http://www.cnblogs.com/imlucky/archive/2013/08/08/3246013. ...

  3. Ant、Maven、Gradle

    android Gradle project http://www.ibm.com/developerworks/cn/opensource/os-cn-gradle/ http://www.voge ...

  4. hdu 2028

    PS:以前对long long型的数据就一直不怎么明白...弄了好久... long long a; scanf("%lld",&a); printf("%lld ...

  5. BZOJ 1060 时态同步

    贪心. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> ...

  6. PHP中函数的使用

    函数是一种可以在任何被需要的时候执行的代码块函数的定义    1.函数是一个被命名的独立的代码段    2.它执行特殊的任务    3.并可以给调用它的程序返回值 函数的优点:    1.提高程序的重 ...

  7. List<T>Contains, Exists, Any之间的优缺点对比

    在List<T>中,Contains, Exists, Any都可以实现判断元素是否存在. 性能方面:Contains 优于 Exists 优于 Any 测试的代码: public sta ...

  8. Android的切图标准

    最近总是有人在问我,Android怎么切图啊,怎么适配啊,不只是Android同行,还有很多新手ui设计师. 于是我就写篇文章,根据我们平时的开发经验,简单的介绍一下吧. 如果UI设计师以1920*1 ...

  9. Android弹出选项框及指示箭头动画选择

     Android弹出选项框及指示箭头动画选择 Android原生的Spinner提供了下拉列表选项框,但在一些流行的APP中,原生的Spinner似乎不太受待见,而通常会有下图所示的下拉列表选项框 ...

  10. JLOI 斯迈利的赌注

    直接高精度模拟,加上简单贪心 Program XJOI2263; ..] of longint; var a,b:arr; s1,s2:ansistring; i,j:longint; sum:int ...