简体   繁体   中英

Pivoting a table in iSeries DB2 dynamically

So what I'm trying to do is convert rows into columns. This has been covered before on this site in a verity of ways, the way I like the best is as follows:

SELECT 
  FRNPCM032.WFP.WFORD#,
  MAX(CASE WHEN FRNPCM032.WFP.WFSEGN = 'COLOR1'  THEN WFVAL END) AS COLOR,
  MAX(CASE WHEN FRNPCM032.WFP.WFSEGN = 'OSKVA'  THEN WFVAL END) AS KVA,
  MAX(CASE WHEN FRNPCM032.WFP.WFSEGN = 'OSSWITCH'  THEN WFVAL END) AS LBSWITCH
FROM FRNPCM032.WFP
GROUP BY FRNPCM032.WFP.WFORD#;

This is a very simple way, but I need something less manual than this because new rows might be added later and I dont want to have to go back to keep maintaining a query or view.

Is there a way I can dynamically do this? I can think of a way to do it with loops, but i cant do that in a query or view.

Unfortunately, DB2 for IBM i doesn't have a PIVOT() function...

However, you can build a procedure that dynamically looks at the current contents of the table and builds an SQL statement that pivots the data.

The following code was taken from the article, An SQL Pivot Procedure

If you wanted you could modify the code to build a view, rather than returning a result set. But you'd have to rebuild the view if the pivot values changed.

CREATE PROCEDURE DO_PIVOT
   (IN FOR_SCHEMA CHARACTER (10) , 
    IN FOR_TABLE CHARACTER (10) , 
    IN PIVOT_COLUMN VARCHAR (250) , 
    IN VALUE_COLUMN VARCHAR (250) , 
    IN AGG_FUNCTION VARCHAR (5) DEFAULT 'SUM' , 
    IN GROUP_COLUMN VARCHAR (250) DEFAULT NULL ) 
    LANGUAGE SQL 
    MODIFIES SQL DATA 
    PROGRAM TYPE SUB 
    CONCURRENT ACCESS RESOLUTION DEFAULT 
    DYNAMIC RESULT SETS 1 
    OLD SAVEPOINT LEVEL COMMIT ON RETURN NO 

BEGIN

   DECLARE SQLCODE INTEGER DEFAULT 0 ;
   DECLARE SQL_STATEMENT VARCHAR ( 5000 ) ;
   DECLARE PIVOT_VALUE VARCHAR ( 20 ) ;
   DECLARE PAD CHAR ( 2 ) DEFAULT ' ' ;

   DECLARE C1 CURSOR FOR D1 ;
   DECLARE C2 CURSOR WITH RETURN FOR D2 ;

   SET SCHEMA = FOR_SCHEMA ;

   -- Get the list of values available for the pivot column
   -- Each value will be a column in the return set
   SET SQL_STATEMENT = 'select distinct ' 
                       || PIVOT_COLUMN  
                       || ' from ' 
                       || FOR_TABLE 
                       || ' order by 1' ;

   PREPARE D1 FROM SQL_STATEMENT ;
   OPEN C1 ;

   -- Construct a dynamic select statement for the pivot
   SET SQL_STATEMENT = 'select ' ;

   -- If requested, add the Group By Column 
   -- to the select clause
   IF GROUP_COLUMN IS NOT NULL THEN
      SET SQL_STATEMENT = SQL_STATEMENT || GROUP_COLUMN ;
      SET PAD = ', ' ;
   END IF ;

   -- For each possible value for the Pivot Column, 
   -- add a case statement to perform the requested 
   -- aggregate function on the Value Column
   FETCH NEXT FROM C1 INTO PIVOT_VALUE ;
   WHILE ( SQLCODE >= 0 AND SQLCODE <> 100 ) DO
      SET SQL_STATEMENT = SQL_STATEMENT 
                          || PAD 
                          || AGG_FUNCTION 
                          || '(CASE WHEN ' 
                          || PIVOT_COLUMN 
                          || ' = ''' 
                          || PIVOT_VALUE 
                          || ''' THEN ' 
                          || VALUE_COLUMN 
                          || '  END) AS ' 
                          || PIVOT_VALUE ;
      SET PAD = ', ' ;
      FETCH NEXT FROM C1 INTO PIVOT_VALUE ;
   END WHILE ;
   CLOSE C1 ;

   -- Specify the table to select from
   SET SQL_STATEMENT = SQL_STATEMENT 
                       || ' from ' 
                       || FOR_TABLE ;

   -- If requested, add the Group By Column
   -- to the select clause
   IF GROUP_COLUMN IS NOT NULL THEN
      SET SQL_STATEMENT = SQL_STATEMENT 
                          || ' group by ' 
                          || GROUP_COLUMN 
                          || ' order by ' 
                          || GROUP_COLUMN;
   END IF ;

   PREPARE D2 FROM SQL_STATEMENT ;
   OPEN C2 ;

END ;

LABEL ON ROUTINE DO_PIVOT 
   ( CHAR(), CHAR(), VARCHAR(), VARCHAR(), VARCHAR(), VARCHAR() )  
   IS 'Perform a General Purpose Pivot';

COMMENT ON PARAMETER ROUTINE DO_PIVOT 
   ( CHAR(), CHAR(), VARCHAR(), VARCHAR(), VARCHAR(), VARCHAR() ) 
   (FOR_SCHEMA IS 'Schema for Table' , 
    FOR_TABLE IS 'For Table' , 
    PIVOT_COLUMN IS 'Name of Column to be Pivoted' , 
    VALUE_COLUMN IS 'Column to be Aggregated for Pivot' , 
    AGG_FUNCTION IS 'Use Aggregate Function' , 
    GROUP_COLUMN IS 'Group on Column' ) ;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM