SAP Sybase ASA对表的Pivot/Unpivot的实现

针对表各列进行Pivot/Unpivot的实现,通俗来讲,就是行转列,列转行的操作。

1. 示例:

比如,

Date              Name       salary
---               ---        -----  
1/1/2012          jay          50
1/1/2012          ken          60
1/2/2012          ken          60
1/2/2012          jay          50
1/3/2012          jay          55
1/3/2012          lisa         80
....
想经过转换以后,得到下边的结果:

Date,      ken,   Jay,   Lisa 
 1/1/2012    60     50       0 
 1/2/2012    60     50       0 
 1/3/2012    0      55       80
一个支持Pivot/Unpivot语法的SQL语句,应该是下边这个样子的:

SELECT newPivot.*
    FROM (SELECT Date, Name, Salary
        FROM DBA.Salary ) AS source
    PIVOT
    ( SUM(source.Salary)
      FOR source.Name IN (Ken AS KEN, Jay AS JAY, Lisa AS LISA)
    ) AS newPivot

Date    KEN JAY LISA
1/1/2012    60  50  0
1/2/2012    60  50  0
1/3/2012    0   55  80
可惜的是ASA目前不支持PIVOT语法。

2. 具体实验

1) 初始化数据:

SQL语句如下:
BEGIN
DROP TABLE t1;
EXCEPTION WHEN OTHERS THEN
END;
 
CREATE TABLE t1 (
c1 VARCHAR ( 10 ) NOT NULL,
c2 VARCHAR ( 10 ) NOT NULL,
c3 INTEGER        NOT NULL,
PRIMARY KEY ( c1, c2 ) );

INSERT t1 VALUES ( 'CA', 'Q1', 1000 );
INSERT t1 VALUES ( 'CA', 'Q2', 2000 );
INSERT t1 VALUES ( 'CA', 'Q3', 9000 );
INSERT t1 VALUES ( 'CA', 'Q4', 7000 );
INSERT t1 VALUES ( 'NY', 'Q1', 4000 );
INSERT t1 VALUES ( 'NY', 'Q2', 5000 );
INSERT t1 VALUES ( 'NY', 'Q3', 1000 );
INSERT t1 VALUES ( 'NY', 'Q4', 6000 );
INSERT t1 VALUES ( 'FL', 'Q1', 9000 );
INSERT t1 VALUES ( 'FL', 'Q2', 7000 );
INSERT t1 VALUES ( 'FL', 'Q3', 2000 );
INSERT t1 VALUES ( 'FL', 'Q4', 1000 );
INSERT t1 VALUES ( 'AZ', 'Q1', 5000 );
INSERT t1 VALUES ( 'AZ', 'Q2', 5000 );
INSERT t1 VALUES ( 'AZ', 'Q3', 1000 );
INSERT t1 VALUES ( 'AZ', 'Q4', 3000 );
INSERT t1 VALUES ( 'MA', 'Q1', 2000 );
INSERT t1 VALUES ( 'MA', 'Q2', 6000 );
INSERT t1 VALUES ( 'MA', 'Q3', 5000 );
INSERT t1 VALUES ( 'MA', 'Q4', 3000 );
COMMIT;

SELECT * FROM t1 ORDER BY c1, c2;

所有的数据如下:
c1,c2,c3
'AZ','Q1',5000
'AZ','Q2',5000
'AZ','Q3',1000
'AZ','Q4',3000
'CA','Q1',1000
'CA','Q2',2000
'CA','Q3',9000
'CA','Q4',7000
'FL','Q1',9000
'FL','Q2',7000
'FL','Q3',2000
'FL','Q4',1000
'MA','Q1',2000
'MA','Q2',6000
'MA','Q3',5000
'MA','Q4',3000
'NY','Q1',4000
'NY','Q2',5000
'NY','Q3',1000
'NY','Q4',6000
用户想要看到这样的结果:

1. c2   AZ    CA    FL    MA    NY
2. Q1  5000  1000  9000  2000  4000
3. Q2  5000  2000  7000  6000  5000
4. Q3  1000  9000  2000  5000  1000
5. Q4  3000  7000  1000  3000  6000

实现的目的如下,将c1列的各午值旋转到新列里头.
BEGIN
    DECLARE @sql LONG VARCHAR;
    SET @sql = 'SELECT c2';
    FOR f_fetch
        AS c_fetch NO SCROLL CURSOR FOR
            SELECT DISTINCT t1.c1 AS @c1
            FROM t1
            ORDER BY t1.c1
            FOR READ ONLY
        DO
        SET @sql = STRING (
            @sql,
            ', SUM ( ( IF t1.c1 = ''',
            @c1,
            ''' THEN 1 ELSE 0 ENDIF ) * t1.c3 ) AS "',
            @c1,
            '"' );
    END FOR;
    SET @sql = STRING (
    @sql,
    ' INTO #t1 FROM t1 GROUP BY c2' );
    MESSAGE @sql TO CONSOLE;
    EXECUTE IMMEDIATE @sql;
    SELECT * FROM #t1 ORDER BY c2; -- pivot table
END;

用户如想看到下述结果:
1. c1   Q1    Q2    Q3    Q4
2. AZ  5000  5000  1000  3000
3. CA  1000  2000  9000  7000
4. FL  9000  7000  2000  1000
5. MA  2000  6000  5000  3000
6. NY  4000  5000  1000  6000

则需要将列c2各行的值进行旋转列(pivot) 操作:
BEGIN
    DECLARE @sql LONG VARCHAR;
    SET @sql = 'SELECT c1';
    FOR f_fetch
        AS c_fetch NO SCROLL CURSOR FOR
        SELECT DISTINCT t1.c2 AS @c2
        FROM t1
        ORDER BY t1.c2
        FOR READ ONLY
    DO
        SET @sql = STRING (
        @sql,
        ', SUM ( ( IF t1.c2 = ''',
        @c2,
        ''' THEN 1 ELSE 0 ENDIF ) * t1.c3 ) AS "',
        @c2,
        '"' );
    END FOR;
    SET @sql = STRING (
    @sql,
    ' INTO #t1 FROM t1 GROUP BY c1' );
    MESSAGE @sql TO CONSOLE;
    EXECUTE IMMEDIATE @sql;
    SELECT * FROM #t1 ORDER BY c1; -- pivot table
END;

实现的关键就是使用1或者0,进行SUM求和。 上述两个过程得到的SQL语句如下:
SELECT c2, 
SUM ( ( IF t1.c1 = 'AZ' THEN 1 ELSE 0 ENDIF ) * t1.c3 ) AS "AZ", 
SUM ( ( IF t1.c1 = 'CA' THEN 1 ELSE 0 ENDIF ) * t1.c3 ) AS "CA", 
SUM ( ( IF t1.c1 = 'FL' THEN 1 ELSE 0 ENDIF ) * t1.c3 ) AS "FL", 
SUM ( ( IF t1.c1 = 'MA' THEN 1 ELSE 0 ENDIF ) * t1.c3 ) AS "MA", 
SUM ( ( IF t1.c1 = 'NY' THEN 1 ELSE 0 ENDIF ) * t1.c3 ) AS "NY" 
INTO #t1 FROM t1 GROUP BY c2

SELECT c1, 
SUM ( ( IF t1.c2 = 'Q1' THEN 1 ELSE 0 ENDIF ) * t1.c3 ) AS "Q1", 
SUM ( ( IF t1.c2 = 'Q2' THEN 1 ELSE 0 ENDIF ) * t1.c3 ) AS "Q2", 
SUM ( ( IF t1.c2 = 'Q3' THEN 1 ELSE 0 ENDIF ) * t1.c3 ) AS "Q3", 
SUM ( ( IF t1.c2 = 'Q4' THEN 1 ELSE 0 ENDIF ) * t1.c3 ) AS "Q4" 
INTO #t1 FROM t1 GROUP BY c1

期盼着Pivot/Unpivot操作早些在ASA中实现。似乎SQLServer已经实现了此功能。



你可能感兴趣的:(SAP Sybase ASA对表的Pivot/Unpivot的实现)