zoukankan      html  css  js  c++  java
  • 简化实现动态行列转置的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、简单的行转列

           一般的行转列仅仅简单地将数据行转为结果列。不涉及复杂的列间计算。

    如将以下的学生成绩表转为分科目展示的集合:


            目标结果:

            实现脚本:


            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就非常困难了。如本例中每类机制生产的产品列数不定:


            要求依据最大的机组分组长度决定转换后的结果列数。目标结果:

            实现脚本:


            A1:运行sql从产量表中取数;

            A2:按机组分组。在集算器中分组结果保留了分组结果(成员)以方便兴许使用和计算;

            A3:求分组中最大成员个数,以确定结果集列数;

            A4-A5:动态创建空结果集;

            A6-B7:循环A2中分组结果。将每一个分组中的类别和产量写入A5结果序表中。

            与上述类似。这段代码仍然是先动态生成空结果集。然后再计算出合适的数据追加。

     

           本例的计算须要写出动态的SQL来拼出结果集,但因为要找出最大的组才知道列数。拼结果也不是像一般的pivot那样能够用字段值直接相应成列。这就要写存储过程一步步地完毕才方便。

           相对照较复杂的存储过程,集算脚本支持过程性计算,代码更加简洁、易编写。

            3、包括列间计算的行转列

           如開始提到的,行列转换的同一时候往往伴随列间计算,比如有数据:

            要求依据指定年份(如2014),输出每月应付金额,若无当月数据,则当月应付金额为上月该值。

     

            目标结果:

            实现脚本:


            A1:运行SQL取查询年数据;

            A2:生成带有12个月的结果空序表;

            A3:按客户分组;

            A4-B7:循环分组。B5设置对应月份的应付金额。B6将空值置为前一个月的数值。B7将记录插入结果序表中。

     

           运算过程仍然是先产生空结果集后追加数据,不同的是。这里要追加的数据须要常常一系列计算才干得到。

           集算脚本支持有序运算。所以非常easy取到前一条记录的值。对于动态行列转换时发生的列间计算。与复杂SQL或存储过程相比。集算脚本更清晰易懂。

            4、列转行

           除了上述提到的转置,有时还有将一行多列数据转为多行数据(列转行)。例如以下数据,当中列数不定:


            目标结果:

            实现脚本:


            A1:运行SQL取数;

            A2:创建目标结果空序表;

            A3:依据A1集合的列数计算每条记录要拆分的行数;

            A4-B4:循环A1集合,动态获取每列数据插入A2结果序表中。



  • 相关阅读:
    PAT 1088. Rational Arithmetic
    PAT 1087. All Roads Lead to Rome
    PAT 1086. Tree Traversals Again
    PAT 1085. Perfect Sequence
    PAT 1084. Broken Keyboard
    PAT 1083. List Grades
    PAT 1082. Read Number in Chinese
    求最大公因数
    [转载]Latex文件转成pdf后的字体嵌入问题的解决
    [转载]Matlab有用的小工具小技巧
  • 原文地址:https://www.cnblogs.com/liguangsunls/p/7402383.html
Copyright © 2011-2022 走看看