不固定列动态行转列SQL
行转列在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相关推荐
- sql 纵向求和_【IT专家】SQL2000 动态行转列+ 横向纵向合计的问题
本文由我司收集整编,推荐下载,如有疑问,请与我司联系 SQL2000 动态行转列 + 横向纵向合计的问题 2014/07/25 10 动态行转列 + 横向纵向合计 createtabletb( 姓名 ...
- mysql行转列sql函数_sql动态行转列的两种方法
第一种方法: 代码如下: select *from ( select Url,case when Month=01 then '1月' when Month=02 then '2月' when ...
- 金蝶K3直接SQL报表实现动态行转列报表
我们知道,在BOS开发中,想实现动态行转列报表,可以使用交叉分析表来实现,但交叉分析表不太灵活,比如当动态列中有需要复杂的逻辑运算来实现时就无能为力了,下面介绍使用直接SQL报表来实现,也许能给你一点 ...
- oracle 动态行转成列,Oracle 行转列 动态出转换的列
一.运行环境 Win10,Oracle Database 11g r2,plsql 12. 二.效果预览 1.固定转换列的方法 2.存储过程处理 1)调用存储过程 2)查指定的视图即可 3.两种方法的 ...
- mysql中将列动态转换为行,mysql 行转列 MySQL数据库动态行转列
想把mysql一个表的行转成列,图1是原表,想实现图2的样式SELECT MAX(CAS就是一个动态的行列转换 CREATE TABLE `c_wssb_zz` ( `aa011` varchar(1 ...
- 动态行转列:处理不确定数量的行转列操作
目录 介绍 分析过程 数据样例 开始动手 添加辅助列 全连接换左连接 完成静态SQL 将动态部分设置到变量 改编为动态SQL 验证 总结 介绍 行转列操作是一种常见的数据转换技术,它可以将原始的行数据 ...
- Excel实现动态行转列(数据透视表)
固定行转列比较容易实现. 但是动态行转列的需求,用SQL都难以实现,要不然就是超级复杂. 不过很多第三方工具都已经提供了很好的支持,不一定非得用SQL实现.比如帆软报表和Excel. 最近接到一个比较 ...
- mssql 动态行转列。
mssql 动态行转列. create table #a (a int , b char(4)) insert into #a select 1,'张三' insert into #a select ...
- mysql动态行转列函数_[MSSQL]采用pivot函数实现动态行转列
环境要求:2005+ 在日常需求中经常会有行转列的事情需求处理,如果不是动态的行,那么我们可以采取case when 罗列处理. 在sql 2005以前处理动态行或列的时候,通常采用拼接字符串的方法处 ...
最新文章
- 你的厨房被水淹了!别担心,这只是3D深度估计做出的特效
- 《C++ Primer Plus》学习笔记——C++程序创建到运行的整个过程
- 一秒搭建gitbook
- redis High Availability---Redis Sentinel翻译
- C语言函数调用的原理
- 软件测试作业7:构建弱健壮的等价类测试用例
- 关于dlg和pro的问题
- 最大子矩阵(信息学奥赛一本通-T1282)
- 汇编 align_从零开始自制操作系统(5):实模式汇编(二)
- Qt 中使用UDP传送大图片(文件)的方法
- Mac 安装 home Brew以及 XCTool的过程记录
- 送书 | 《深入浅出Python机器学习》
- 如何在IDEA上创建一个JSP项目【亲测有效】
- 代码整洁之道-编写 Pythonic 代码
- 云计算对21世纪IT人的挑战
- MathJax 支持的 Latex 符号总结(各种箭头符号)
- 玩转云服务器,怎样用云服务器架设搭建游戏:浪剑天下架设教程,手把手教你架设游戏服务器,小白一看就会
- 修复文件关联-EXE文件关联被修改后所有应用程序都打不开
- mysql count函数 null_MySql中COUNT(XXX OR NULL)
- Go 语言编程 — 高级数据类型 — Interface、多态、Duck Typing 与泛式编程
热门文章
- 基于HTML5的棋盘游戏开发,基于HTML5的网页围棋游戏的开发
- MOSFET(二):米勒效应
- redhat双系统Linux引导,用wingrub引导windows与redhat linux双系统
- OCR--服务器端身份证识别系统的原理及应用
- 有人给你的长相“跑分”,有人给你的公司安全“跑分
- 移动web开发视口代码
- 你的变量究竟存储在什么地方 全局内存
- Problem E: GDUT的实验室
- 【树莓派】64G的SD卡无法使用NOOBS安装树莓派的问题
- java visualvm 官方_Java VisualVM使用