web-dev-qa-db-fra.com

Utilisation du pivot sur plusieurs colonnes d'une ligne Oracle

J'ai les exemples de données suivants dans une table Oracle (tab1) Et j'essaie de convertir des lignes en colonnes. Je sais comment utiliser Oracle pivot sur une colonne. Mais est-il possible de l'appliquer à plusieurs colonnes?

Exemples de données:

Type  weight  height  
A     50      10  
A     60      12  
B     40      8  
C     30      15  

Ma sortie prévue:

A-count B-count C-count A-weight B-weight C-weight A-height B-height C-height  
2       1       1       110      40       30       22       8        15  

Qu'est-ce que je peux faire:

with T AS 
(select type, weight from tab1 )
select * from T
PIVOT (
count(type)
for type in (A, B, C, D,E,F)
)  

La requête ci-dessus me donne le résultat ci-dessous

A B C  
2 1 1  

Je peux remplacer count(*) par sum(weight) ou sum(height) pour faire pivoter la hauteur ou le poids. Ce que je cherche à faire, mais je ne peux pas le faire, c'est pivoter sur les trois (nombre, poids et taille) en une seule requête.

Peut-on le faire en utilisant le pivot?

15
Badal

Comme la documentation le montre , vous pouvez avoir plusieurs clauses de fonction d'agrégation. Vous pouvez donc faire ceci:

select * from (
  select * from tab1
)
pivot (
  count(type) as ct, sum(weight) as wt, sum(height) as ht
  for type in ('A' as A, 'B' as B, 'C' as C)
);

A_CT A_WT A_HT B_CT B_WT B_HT C_CT C_WT C_HT
---- ---- ---- ---- ---- ---- ---- ---- ----
   2  110   22    1   40    8    1   30   15 

Si vous voulez que les colonnes soient dans l'ordre que vous avez affiché, ajoutez un autre niveau de sous-requête:

select a_ct, b_ct, c_ct, a_wt, b_wt, c_wt, a_ht, b_ht, c_ht
from (
  select * from (
    select * from tab1
  )
  pivot (
    count(type) as ct, sum(weight) as wt, sum(height) as ht
    for type in ('A' as A, 'B' as B, 'C' as C)
  )
);

A_CT B_CT C_CT A_WT B_WT C_WT A_HT B_HT C_HT
---- ---- ---- ---- ---- ---- ---- ---- ----
   2    1    1  110   40   30   22    8   15 

SQL Fiddle .

25
Alex Poole

La deuxième approche pour nommer les colonnes est encore meilleure et résout plus de problèmes. J'avais une exigence où je voulais résumer les données renvoyées par PIVOT, donc ayant des noms de colonne, je pouvais simplement ajouter 2 et obtenir le résultat requis dans le troisième -

select a_ct, b_ct, c_ct, a_wt, b_wt, c_wt, a_ht, b_ht, c_ht, a_wt + b_wt + c_wt tot_wt
from (
  select * from (
    select * from tab1
  )
  pivot (
    count(type) as ct, sum(weight) as wt, sum(height) as ht
    for type in ('A' as A, 'B' as B, 'C' as C)
  )
);

A_CT B_CT C_CT A_WT B_WT C_WT A_HT B_HT C_HT TOT_WT
---- ---- ---- ---- ---- ---- ---- ---- ---- ------
   2    1    1  110   40   30   22    8   15 180

Gardez juste à l'esprit que les fonctions d'agrégation (comme sum) ne se comporteront pas comme prévu si l'une des colonnes PIVOT utilisées retourne null, dans ce cas, j'ai utilisé l'instruction CASE pour contourner ce problème.

J'espère que cela aide quelqu'un.

1
Amit S