简化实现动态行列转置的SQL
动态行列转换的计算在实际业务中非经常见,网上各类技术论坛上都有讨论,比方以下这些问题:
http://www.iteye.com/problems/87788
http://bbs.csdn.net/topics/390869577
http://bbs.csdn.net/topics/391000711
http://bbs.csdn.net/topics/391001035
http://bbs.csdn.net/topics/390888703
http://bbs.csdn.net/topics/391012377
http://bbs.csdn.net/topics/390956910
http://bbs.csdn.net/topics/391004719
http://bbs.csdn.net/topics/390946260
http://bbs.csdn.net/topics/390937222?page=1#post-398564938
http://bbs.csdn.net/topics/390883416
http://bbs.csdn.net/topics/390960953
http://bbs.csdn.net/topics/390959646
行转列使用SQL完毕一般有下面几种方法:
1、 使用行列转换函数
Oracle11g及以上和MSSQL2005+提供了行列转置运算符pivot和unpivot,前者用于行转列,后者用于列转行。使用时须要指定目标列,对于动态列的场景无法直接完毕。
2、 使用CASE表达式
对于不支持pivot的数据库。如Mysql、DB2。能够使用case when条件表达式完毕。与pivot类似,须要依据目标列固定写死,无法直接写出动态列结构转换。
对于动态列的情况。仅仅能:
3、 拼接动态SQL
处理动态行列转换时往往须要在存储过程中拼接动态SQL完毕,因为数据库间的差异,写法与难易程度也不尽同样。无法编写通用的SQL语句。
实际情况中中,行列转换往往还伴随列间计算。增大了转置时的难度。
行列转换的目的经常是为了进一步的数据呈现。也就是说会有个主程序(如报表工具等)接受结果以进行下一步操作。假设是Java主程序,则能够使用润乾集算器(免费版)来协助完毕这类转换。集算器是动态解释运行的脚本。完毕行列转换的代码更具通用性。
集算器提供了JDBC接口,能够置于Java应用程序与数据库之间。让应用程序继续象訪问数据库一样运行集算器脚本,不用改变应用结构。
以下以一个简单的样例说明用集算器怎样实现行列转换。并集成进Java主程序中。
1、简单的行转列
一般的行转列仅仅简单地将数据行转为结果列。不涉及复杂的列间计算。
如将以下的学生成绩表转为分科目展示的集合:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
目标结果:
实现脚本:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
A1:运行SQL取数,并按ID、SUBJECT排序;
A2-A3:按ID和SUBJECT分组,集算器保留了分组后的子集供后面计算使用;
A4:动态创建空的目标结果集;
A5-B5:循环A2的学生分组,依据SUBJECT分组将学生ID、姓名和各科目成绩写入结果集;
A6:返回结果集。
从上面代码能够看出採用集算器实现行转列的基本步骤:先动态计算出空的目标结果集(A4)。再计算出每行数据追加到结果集中(A5,B5)。在有了支持数据表对象的分步计算机制后,行转列的过程能够按自然思路编写出来。
集算脚本的计算结果能够用JDBC接口返回给JAVA主程序或报表工具,JAVA调用集算脚本代码:
Class.forName("com.esproc.jdbc.InternalDriver");
con=DriverManager.getConnection("jdbc:esproc:local://");
//调用集算器脚本(类似存储过程),当中p1是集算器脚本文件名称
st=(com. esproc.jdbc.InternalCStatement)con.prepareCall("call p1 ()");
//运行脚本
st.execute();
//获取结果集
ResultSetrs = st.getResultSet();
……
返回值是符合JDBC标准的ResultSet对象,调用集算器脚本和訪问数据库的方法全然一样,熟悉JDBC的程序猿能够非常快掌握。
关于集算器JDBC的部署和调用的更具体信息可參考【集算器集成应用之被JAVA调用】。
2、不定长分组的行转列
上一个样例中,结果集的列(即科目)常常能够事先获知,这样用静态的pivot(或case when)语法写出来也不算非常困难。但假设结果集的列须要动态计算出来,用pivot就非常困难了。如本例中每类机制生产的产品列数不定:
要求依据最大的机组分组长度决定转换后的结果列数。目标结果:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
实现脚本:
A1:运行sql从产量表中取数;
A2:按机组分组。在集算器中分组结果保留了分组结果(成员)以方便兴许使用和计算;
A3:求分组中最大成员个数,以确定结果集列数;
A4-A5:动态创建空结果集;
A6-B7:循环A2中分组结果。将每一个分组中的类别和产量写入A5结果序表中。
与上述类似。这段代码仍然是先动态生成空结果集。然后再计算出合适的数据追加。
本例的计算须要写出动态的SQL来拼出结果集,但因为要找出最大的组才知道列数。拼结果也不是像一般的pivot那样能够用字段值直接相应成列。这就要写存储过程一步步地完毕才方便。
相对照较复杂的存储过程,集算脚本支持过程性计算,代码更加简洁、易编写。
3、包括列间计算的行转列
如開始提到的,行列转换的同一时候往往伴随列间计算,比如有数据:
要求依据指定年份(如2014),输出每月应付金额,若无当月数据,则当月应付金额为上月该值。
目标结果:
实现脚本:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
A1:运行SQL取查询年数据;
A2:生成带有12个月的结果空序表;
A3:按客户分组;
A4-B7:循环分组。B5设置对应月份的应付金额。B6将空值置为前一个月的数值。B7将记录插入结果序表中。
运算过程仍然是先产生空结果集后追加数据,不同的是。这里要追加的数据须要常常一系列计算才干得到。
集算脚本支持有序运算。所以非常easy取到前一条记录的值。对于动态行列转换时发生的列间计算。与复杂SQL或存储过程相比。集算脚本更清晰易懂。
4、列转行
除了上述提到的转置,有时还有将一行多列数据转为多行数据(列转行)。例如以下数据,当中列数不定:
目标结果:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
实现脚本:
A1:运行SQL取数;
A2:创建目标结果空序表;
A3:依据A1集合的列数计算每条记录要拆分的行数;
A4-B4:循环A1集合,动态获取每列数据插入A2结果序表中。
简化实现动态行列转置的SQL的更多相关文章
- SQL动态长度行列转置
一,案列问题描述: 某销售系统中,注册的用户会在随后的月份中购物下单,需要按月统计注册的用户中各个月下单的金额.源数据表如下: FM::注册月份,CM: 下单月份, AMT:下单金额 期望得到如下统计 ...
- 使用SQL SERVER PIVOT实现行列转置
一般我们在使用SQL语句实现行列转置时候,最常用的方法无外乎就是 case语句来实现,但是如果需要需要转置的列太多,那么case起来语句就无限庞大,十分不方便,sql server中的PIVOT就可以 ...
- sql server动态行列转换
原文链接:https://www.cnblogs.com/gaizai/p/3753296.html sql server动态行列转换 一.本文所涉及的内容(Contents) 本文所涉及的内容(Co ...
- HAWQ中的行列转置
行列转置是ETL或报表系统中的常见需求,HAWQ提供的内建函数和过程语言编程功能,使行列转置操作的实现变得更为简单. 一.行转列 1. 固定列数的行转列 原始数据如下: test=# select * ...
- Excel 行列转置 解决竖向拉,字母跟着递增的问题
今天工作中遇到需要将Excel行列转置涉及到的数据单元格一共几千个 查询网上说可以通过复制粘贴单元格,粘贴选项中转置一项实现,但是所涉及的sheet页中,数据格式和单元格格式各不一样,转置失败! 怎么 ...
- 用powershell+excel行列转置三步走
本文重点讲解第一步,手动在excel表中输入公式,或者用powershell自动输入公式. 第二步,用powershell向excel中写入数据,略. 第三步,用powershell从excel中读取 ...
- Oracle 行列转置
两种简单的行列转置 1.固定列数的行列转换如student subject grade--------- ---------- --------student1 语文 80st ...
- 行列转置(Oracle)
一.Oracle行列转置 1.行转列 (1)创建表格.插入测试数据 create table student( id number, name ), course ), score number ) ...
- MySQL中行列转换的SQL技巧
行列转换常见场景 由于很多业务表因为历史原因或者性能原因,都使用了违反第一范式的设计模式.即同一个列中存储了多个属性值(具体结构见下表). 这种模式下,应用常常需要将这个列依据分隔符进行分割,并得到列 ...
随机推荐
- Codeforces Round #541 (Div. 2) (A~F)
目录 Codeforces 1131 A.Sea Battle B.Draw! C.Birthday D.Gourmet choice(拓扑排序) E.String Multiplication(思路 ...
- BZOJ.4558.[JLOI2016]方(计数 容斥)
BZOJ 洛谷 图基本来自这儿. 看到这种计数问题考虑容斥.\(Ans=\) 没有限制的正方形个数 - 以\(i\)为顶点的正方形个数 + 以\(i,j\)为顶点的正方形个数 - 以\(i,j,k\) ...
- Shell脚本笔记(六)呈现数据
呈现数据 一.文件描述符 Linux系统将每个对象当做文件处理,这包括输入和输出进程.Linux用文件描述符来标识每个文件对象.每个进程最多可以有9个 文件描述符,bash shell保留了前三个文件 ...
- 让资源管理器变得像Chrome一样标签化
让资源管理器变得像Chrome一样标签化 前段时间WIn10开发者预览版发布了更新通知,其中一个主要特性就是给资源管理器添加了标签化的功能. 习惯了各种浏览器便捷的标签化管理,早就想要这个实用的功能了 ...
- yii去掉自动排序功能
Yii去掉自动排序功能并自定义排序 public function search($params) { $query = SvnManage::find()->addOrderBy([ 'cre ...
- c# 后台绑定treeview 单个tab
<wijmo:C1TreeView ID="C1TreeView1" runat="server" ShowCheckBoxes="true&q ...
- C_关于递归算法的几个例子
1.递归算法的定义: 2.递归与迭代的优劣 eg1:斐波那契数列:斐波那契数列(Fibonacci sequence),又称黄金分割数列.因数学家列昂纳多·斐波那契(Leonardoda Fibona ...
- Vue(十三)自定义指令
自定义指令 分类:全局指令.局部指令 1. 自定义全局指令 使用全局方法Vue.directive(指令ID,定义对象) 2. 自定义局部指令 <!DOCTYPE html> < ...
- ES6项目构建(babel+gulp+webpack)
(一)基础架构 (二)任务自动化(gulp) (三)编译工具(babel,webpack) (四)代码实现 一.基础构架 1.app : 放置前端代码 css : css文件 js : js文件 cl ...
- 【动态规划】Column Addition @ICPC2017Tehran/upcexam5434
时间限制: 1 Sec 内存限制: 128 MB 题目描述 A multi-digit column addition is a formula on adding two integers writ ...