行转列在sql的应用中比较常用,但现在互联网数据应用中,往往获取的都是json,而且里面的字段解析出来后列都是不固定的,多的话几百个字段都不出奇,经常我们要根据这些字段进行汇总,就涉及到了动态行转列的问题。下面举个例子实现动态行转列。这个例子是要按照每个商店,每种商品计算销售量。

1. 创建测试表

DROP TABLE IF EXISTS store_sale;
        CREATE TABLE store_sale
         (
                   store_name varchar(64)      comment '商店名称',
                   commodity  varchar(64)      comment '商品名称',
                   sale_count int              comment '销售数量'
         ) ;

2. 准备数据

INSERT INTO store_sale VALUES ('store1', '洗发水', 45);
INSERT INTO store_sale VALUES ('store1', '牛奶', 62);
INSERT INTO store_sale VALUES ('store1', '方便面', 37);
INSERT INTO store_sale VALUES ('store2', '面包', 100);
INSERT INTO store_sale VALUES ('store3', '水果', 87);
INSERT INTO store_sale VALUES ('store1', '香水', 30);
INSERT INTO store_sale VALUES ('store4', '面包', 200);
INSERT INTO store_sale VALUES ('store2', '洗发水', 50);
INSERT INTO store_sale VALUES ('store3', '蔬菜', 40);
INSERT INTO store_sale VALUES ('store4', '大米', 100);
INSERT INTO store_sale VALUES ('store4', '花生油', 50);
INSERT INTO store_sale VALUES ('store2', '花生油', 30);
INSERT INTO store_sale VALUES ('store3', '方便面', 55);
INSERT INTO store_sale VALUES ('store3', '鸡蛋', 85);
INSERT INTO store_sale VALUES ('store2', '鸡蛋', 34);

3. 如果使用静态行转列,写法如下:

SELECT
    store_name,
    MAX(IF(commodity = '大米', sale_count, 0)) AS '大米',
    MAX(IF(commodity = '方便面', sale_count, 0)) AS '方便面',
    MAX(IF(commodity = '水果', sale_count, 0)) AS '水果',
    MAX(IF(commodity = '洗发水', sale_count, 0)) AS '洗发水',
    MAX(IF(commodity = '牛奶', sale_count, 0)) AS '牛奶',
    MAX(IF(commodity = '蔬菜', sale_count, 0)) AS '蔬菜',
    MAX(IF(commodity = '面包', sale_count, 0)) AS '面包',
    MAX(IF(commodity = '香水', sale_count, 0)) AS '香水',
    MAX(IF(commodity = '花生油', sale_count, 0)) AS '花生油',
    MAX(IF(commodity = '鸡蛋', sale_count, 0)) AS '鸡蛋',
    SUM(IFNULL(sale_count,0)) AS '销售总量'
 FROM store_sale
GROUP BY store_name

;

结果为:

4. 动态行转列

如何实现动态行转列?

首先我们获取到列的名称:

SELECT
    GROUP_CONCAT(DISTINCT
            CONCAT('MAX(IF(commodity = ''',commodity,''', sale_count, 0)) AS ''',commodity, ''''
                   ),'\n'
                    )
        FROM store_sale c

;

结果为:

MAX(IF(commodity = '大米', sale_count, 0)) AS '大米'
,MAX(IF(commodity = '方便面', sale_count, 0)) AS '方便面'
,MAX(IF(commodity = '水果', sale_count, 0)) AS '水果'
,MAX(IF(commodity = '洗发水', sale_count, 0)) AS '洗发水'
,MAX(IF(commodity = '牛奶', sale_count, 0)) AS '牛奶'
,MAX(IF(commodity = '蔬菜', sale_count, 0)) AS '蔬菜'
,MAX(IF(commodity = '面包', sale_count, 0)) AS '面包'
,MAX(IF(commodity = '香水', sale_count, 0)) AS '香水'

接着我们可以按照静态行转列的形式,把上结果跟原表拼接成一个动态sql语句。

SET @sql1='', @sql='';

SELECT
        GROUP_CONCAT(DISTINCT
                           concat(
                                    'MAX(IF(commodity = ''',
                                     commodity,
                                    ''', sale_count, 0)) AS ''',
                                    commodity, ''''
                                 )
                    ) INTO @sql1
        FROM store_sale c;
    
        
    SET @sql = CONCAT('Select store_name, ', @sql1,',', 'sum(sale_count) as "总量"',  ' From (select store_name,commodity,sum(ifnull(sale_count,0)) as "sale_count" from store_sale group by store_name,commodity) a group by store_name ');

PREPARE stmt FROM @sql;
EXECUTE stmt;

执行结果为:

结果符合要求,但是,在原表中增加一条记录:

INSERT INTO store_sale VALUES ('store1', '洗发水', 20);

再执行,结果为:

这里发现,store1的总量变成194,增加了20,但洗发水没有变化。原因是group by没有按照洗发水sum操作。于是,我们可以增加一层派生表实现。

SET @sql1='', @sql='';
SELECT
        GROUP_CONCAT(DISTINCT
                           concat(
                                    'MAX(IF(commodity = ''',
                                     commodity,
                                    ''', sale_count, 0)) AS ''',
                                    commodity, ''''
                                 )
                    ) INTO @sql1
        FROM store_sale c;
    
        
    SET @sql = CONCAT('Select store_name, ', @sql1,',', 'sum(sale_count) as "总量"',  ' From (select store_name,commodity,sum(ifnull(sale_count,0)) as "sale_count" from store_sale group by store_name,commodity) a group by store_name ');

执行结果为:

这一次洗发水那一列变成65了。

5. 为了方便,把上面用存储过程重写

CREATE PROCEDURE sp_pivot_nonfixied_column()
BEGIN 
    SET @sql1='', @sql='';
    SELECT
        GROUP_CONCAT(DISTINCT
                           concat(
                                    'MAX(IF(commodity = ''',
                                     commodity,
                                    ''', sale_count, 0)) AS ''',
                                    commodity, ''''
                                 )
                    ) INTO @sql1
        FROM store_sale c;
    
        
    SET @sql = CONCAT('Select store_name, ', @sql1,',', 'sum(sale_count) as "总量"',  ' From (select store_name,commodity,sum(ifnull(sale_count,0)) as "sale_count" from store_sale group by store_name,commodity) a group by store_name ');

PREPARE stmt FROM @sql;
EXECUTE stmt;

END;

调用:

call sp_pivot_nonfixied_column();

不固定列动态行转列SQL相关推荐

  1. sql 纵向求和_【IT专家】SQL2000 动态行转列+ 横向纵向合计的问题

    本文由我司收集整编,推荐下载,如有疑问,请与我司联系 SQL2000 动态行转列 + 横向纵向合计的问题 2014/07/25 10 动态行转列 + 横向纵向合计 createtabletb( 姓名 ...

  2. mysql行转列sql函数_sql动态行转列的两种方法

    第一种方法: 代码如下: select *from ( select Url,case  when  Month=01 then  '1月' when  Month=02 then '2月' when ...

  3. 金蝶K3直接SQL报表实现动态行转列报表

    我们知道,在BOS开发中,想实现动态行转列报表,可以使用交叉分析表来实现,但交叉分析表不太灵活,比如当动态列中有需要复杂的逻辑运算来实现时就无能为力了,下面介绍使用直接SQL报表来实现,也许能给你一点 ...

  4. oracle 动态行转成列,Oracle 行转列 动态出转换的列

    一.运行环境 Win10,Oracle Database 11g r2,plsql 12. 二.效果预览 1.固定转换列的方法 2.存储过程处理 1)调用存储过程 2)查指定的视图即可 3.两种方法的 ...

  5. mysql中将列动态转换为行,mysql 行转列 MySQL数据库动态行转列

    想把mysql一个表的行转成列,图1是原表,想实现图2的样式SELECT MAX(CAS就是一个动态的行列转换 CREATE TABLE `c_wssb_zz` ( `aa011` varchar(1 ...

  6. 动态行转列:处理不确定数量的行转列操作

    目录 介绍 分析过程 数据样例 开始动手 添加辅助列 全连接换左连接 完成静态SQL 将动态部分设置到变量 改编为动态SQL 验证 总结 介绍 行转列操作是一种常见的数据转换技术,它可以将原始的行数据 ...

  7. Excel实现动态行转列(数据透视表)

    固定行转列比较容易实现. 但是动态行转列的需求,用SQL都难以实现,要不然就是超级复杂. 不过很多第三方工具都已经提供了很好的支持,不一定非得用SQL实现.比如帆软报表和Excel. 最近接到一个比较 ...

  8. mssql 动态行转列。

    mssql 动态行转列. create table #a (a int , b char(4)) insert into #a select 1,'张三' insert into #a select ...

  9. mysql动态行转列函数_[MSSQL]采用pivot函数实现动态行转列

    环境要求:2005+ 在日常需求中经常会有行转列的事情需求处理,如果不是动态的行,那么我们可以采取case when 罗列处理. 在sql 2005以前处理动态行或列的时候,通常采用拼接字符串的方法处 ...

最新文章

  1. 你的厨房被水淹了!别担心,这只是3D深度估计做出的特效
  2. 《C++ Primer Plus》学习笔记——C++程序创建到运行的整个过程
  3. 一秒搭建gitbook
  4. redis High Availability---Redis Sentinel翻译
  5. C语言函数调用的原理
  6. 软件测试作业7:构建弱健壮的等价类测试用例
  7. 关于dlg和pro的问题
  8. 最大子矩阵(信息学奥赛一本通-T1282)
  9. 汇编 align_从零开始自制操作系统(5):实模式汇编(二)
  10. Qt 中使用UDP传送大图片(文件)的方法
  11. Mac 安装 home Brew以及 XCTool的过程记录
  12. 送书 | 《深入浅出Python机器学习》
  13. 如何在IDEA上创建一个JSP项目【亲测有效】
  14. 代码整洁之道-编写 Pythonic 代码
  15. 云计算对21世纪IT人的挑战
  16. MathJax 支持的 Latex 符号总结(各种箭头符号)
  17. 玩转云服务器,怎样用云服务器架设搭建游戏:浪剑天下架设教程,手把手教你架设游戏服务器,小白一看就会
  18. 修复文件关联-EXE文件关联被修改后所有应用程序都打不开
  19. mysql count函数 null_MySql中COUNT(XXX OR NULL)
  20. Go 语言编程 — 高级数据类型 — Interface、多态、Duck Typing 与泛式编程

热门文章

  1. 基于HTML5的棋盘游戏开发,基于HTML5的网页围棋游戏的开发
  2. MOSFET(二):米勒效应
  3. redhat双系统Linux引导,用wingrub引导windows与redhat linux双系统
  4. OCR--服务器端身份证识别系统的原理及应用
  5. 有人给你的长相“跑分”,有人给你的公司安全“跑分
  6. 移动web开发视口代码
  7. 你的变量究竟存储在什么地方 全局内存
  8. Problem E: GDUT的实验室
  9. 【树莓派】64G的SD卡无法使用NOOBS安装树莓派的问题
  10. java visualvm 官方_Java VisualVM使用