DB2行列转换

  在开发当中经常会碰到需要进行行列转换及递归的问题:该类问题主要涉及的数据表现形式是

树形结构的数据,诸如机构组织、人事职位等。

1、递归

语法:递归表达式也称为CTE 公用表表达式,其形式如下:

-----------------------------------------------------------  

  with 临时名字(字段列表) as (

    select  语句  //该语句一般为初始化语句,初始化临时视图的

     union all  //该句基本都是需要的 

    递归select语句 //该句执行时会引用前面定义的临时表,然后递归查询,直到返回空结果  

  )

 select语句  //该句从临时表中获取最终想要的结果 

-----------------------------------------------------------

以上结构是最简单的with递归,更复杂的,可能with中有好几个临时视图。

应用举例:

********用递归查询来实现DB2的行列转换问题  ****

假设有这么一个表:

        A        B

        1        a

        2        b

        1        c

        1        d

        3        e

        3        f

查询的结果为:

     1          a,c,d

     2          b

     3          e,f

那么DB2的写法是这样的:

    WITH T1(A,B,NUM) AS   

(   

Select A,B,ROW_NUMBER() OVER(PARTITION BY A orDER BY ID) FROM T  

  ),   

T2(RA,RB,NUM) AS   

(   

Select A,CHAR(B,10),NUM FROM T1 Where NUM = 1   

UNION ALL   

Select T2.RA,RTRIM(T2.RB)||','||T1.B,T1.NUM FROM T1 , T2 Where T1.NUM = T2.NUM + 1 AND T1.A = T2.RA   

)   

Select    

    RA,RB FROM T2    

Where    

    NUM = ( Select MAX(NUM) FROM T2 TEMP Where TEMP.RA = T2.RA)    

orDER BY RA  

2、行列转换

行列转换包括以下六种情况:
*列转行
*行转列
*多列转换成字符串
*多行转换成字符串
*字符串转换成多列
*字符串转换成多行

分类:

 1、固定列数的行列转换

 student subject grade

--------- ---------- --------

student1 语文 80

student1 数学 70

student1 英语 60

student2 语文 90

student2 数学 80

student2 英语 100

……

转换为

语文 数学 英语

student1 80 70 60

student2 90 80 100

……

语句如下(oracle):select student, 

sum(decode(subject,'语文', grade,null)) "语文",

sum(decode(subject,'数学', grade,null)) "数学",

sum(decode(subject,'英语', grade,null)) "英语"

from table

group by student;

2、不定列行列转换

c1 c2

--- -----------

1 我

1 是

1 谁

2 知

2 道

3 不

……

转换为

1 我是谁

2 知道

3 不

3、列数不固定(交叉表行列转置),如按日期统计销售情况

原始数据:

CLASS1     CALLDATE         CALLCOUNT

1          2005-08-08       40

1          2005-08-07       6

2          2005-08-08       77

3          2005-08-09       33

3          2005-08-08       9

3          2005-08-07       21

转置后:

CALLDATE     CallCount1 CallCount2 CallCount3

------------ ---------- ---------- ----------

2005-08-09   0          0          33

2005-08-08   40         77         9

2005-08-07  6      0          21

=====================

下面给出db2中行与列的互转实例:

行转列
给出下面的数据:
CREATE TABLE Sales (Year INT, Quarter INT, Results INT)

YEAR        QUARTER     RESULTS
----------- ----------- -----------
       2004           1          20
       2004           2          30
       2004           3          15
       2004           4          10
       2005           1          18
       2005           2          40
       2005           3          12
       2005           4          27
想要的到结果:
YEAR        Q1          Q2          Q3          Q4
----------- ----------- ----------- ----------- -----------
       2004          20          30          15          10
       2005          18          40          12          27
这个SQL就可解决这个问题:
SELECT Year,
       MAX(CASE WHEN Quarter = 1
           THEN Results END) AS Q1,
       MAX(CASE WHEN Quarter = 2
           THEN Results END) AS Q2,
       MAX(CASE WHEN Quarter = 3
           THEN Results END) AS Q3,
       MAX(CASE WHEN Quarter = 4
           THEN Results END) AS Q4
FROM Sales
GROUP BY Year
利用max原因,因为不加max的话结果会是这样:
YEAR        Q1          Q2          Q3          Q4
----------- ----------- ----------- ----------- -----------
       2004          20           -           -           -
       2004           -          30           -           -
       2004           -           -          15           -
       2004           -           -           -          10
       2005          18           -           -           -
       2005           -          40           -           -
       2005           -           -          12           -
       2005           -           -           -          27


列转行
给出下面数据

CREATE TABLE SalesAgg
(  year INTEGER,
   q1 INTEGER,
   q2 INTEGER,
   q3 INTEGER,
   q4 INTEGER );

YEAR        Q1          Q2          Q3          Q4
----------- ----------- ----------- ----------- -----------
       2004          20          30          15          10
       2005          18          40          12          27

想要的结果
YEAR        QUARTER     RESULTS
----------- ----------- -----------
       2004           1          20
       2004           2          30
       2004           3          15
       2004           4          10
       2005           1          18
       2005           2          40
       2005           3          12
       2005           4          27

这个SQL就可以实现:

SELECT S.Year, Q.Quarter, Q.Results
FROM SalesAgg AS S,
     TABLE (VALUES(1, S.q1),
                  (2, S.q2),
                  (3, S.q3),
                  (4, S.q4))
            AS Q(Quarter, Results);
下面解释一下执行的过程:
核心是用table函数创建了一个表,这个表是用value实现的多行表,value实现虚表的例子:

db2 => select * from (values (1,2),(2,3)) as t1(col1,col2)

COL1        COL2
----------- -----------
          1           2
          2           3


你可能感兴趣的:(DB2行列转换)