2017-10-21 10 views
0

J'ai vu quelques Q/A semblables ici, mais les cas que j'ai vus étaient des variations sur la variété "ventes par année par trimestre", donc DECODE est utilisé, avec 4 catégories.Données DB2 pivotantes - où le nombre de colonnes et de lignes n'est pas fixe

Dans mon cas, je ne sais pas à l'avance combien de lignes ou de colonnes le pivot aura.

| Pay | Age | Value | 

|-----|-----|-------| 

| 1 | 1 | 10 | 

| 1 | 2 | 20 | 

| 1 | 3 | 30 | 

| 2 | 1 | 90 | 

| 2 | 2 | 80 | 

| 2 | 3 | 70 | 

et nous voulons que le résultat est défini comme

PAYGROUP  Millennials  GenX  Boomers 
1    10   20  30    
2    90   80  70 

Ce serait facile avec une déclaration PIVOT, à savoir

Transform Max(VALUE) AS V 
SELECT PAYGROUP 
FROM table 
GROUP BY PAYGROUP 
PIVOT AGEGROUP; 

mais mon DB2 n'a pas de fonction PIVOT. Le nombre de groupes de paie et de groupes d'âge peut varier d'un cas à l'autre, par exemple, les données peuvent avoir des nombres différents de groupes de rémunération et d'âge pour différents cas.

+0

S'il n'est pas corrigé, alors vous devriez envisager de le faire dans votre code d'application – GurV

+0

Aucun RDBMS ne permet les colonnes d'exécution dans une instruction 'PIVOT', puisque les définitions de colonne peuvent ' t être des champs de données. Cela doit être fait avec SQL dynamique. Après avoir obtenu la liste des valeurs 'colonne', les [techniques standard s'appliquent] (https://stackoverflow.com/questions/15529107/pivoting-in-db2) –

Répondre

0

Cela peut être fait, mais uniquement dans le cadre d'une procédure SQL ou d'un autre HLL.

Vous avez utilisé une instruction SQL pour déterminer ce/combien de valeurs distinctes puis créer une instruction SQL dynamique à l'aide de ces valeurs.

Vous pouvez probablement vous diriger vers un exemple si vous ajoutez votre plate-forme et votre version DB2 à la question.

est ici pure procédure SQL (à l'origine pour DB2 for IBM i, mais devrait fonctionner pour LUW) trouvé ici: https://www.itjungle.com/2015/04/21/fhg042115-story01/

SET SCHEMA = WHER_YOU_WANT_IT; 

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') ; 

Je pense que vous pouvez également utiliser les fonctions XML pour faire pivoter les données ... mais Je n'ai pas encore trouvé un bon exemple de cela

+0

C'est DB2/v9 FWIW. Je suis toujours curieux d'une approche SQL intelligente, mais je vais faire pivoter le jeu d'enregistrements "à la dure" dans l'application client (JSP). Encore une solution SQL seulement serait bien. – SteveValarenti