Oracle
 sql >> Base de données >  >> RDS >> Oracle

PIVOT basé sur Oracle avec plusieurs groupes de colonnes

Vous pivotez sur une valeur fixe, le littéral de chaîne 'RM' , donc vous ne faites vraiment rien d'utile dans le pivot - le résultat est le même que celui que vous obtiendriez en exécutant la requête 'pivot_data' seule :

SELECT eNAME,workhrs,room, SCR from PRODUCTIVITY p,PRODUCTIVITYd d, emp e, ROOMS R
where p.PRODUCTIVITYID=d.PRODUCTIVITYID and e.empno=p.employeeid
AND R.ID=P.ROOMID;

ENAME    WORKHRS       ROOM        SCR
----- ---------- ---------- ----------
JONES        3.6        101         53
ALLEN       1.32        101         43
ALLEN          6        102         22

Vous voulez l'agrégat workhrs pour chaque employé, et un pivot des chambres vendues. Si vous modifiez cette requête pour obtenir la somme analytique de workhrs et un classement des valeurs room/scr (et en utilisant la syntaxe de jointure moderne) que vous obtenez :

select e.ename, r.room, p.scr,
  sum(d.workhrs) over (partition by e.ename) as wrkhrs,
  rank() over (partition by e.ename order by r.room, p.scr) as rnk
from productivity p
join productivityd d on d.productivityid = p.productivityid
join emp e on e.empno=p.employeeid
join rooms r on r.id = p.roomid;

ENAME       ROOM        SCR     WRKHRS        RNK
----- ---------- ---------- ---------- ----------
ALLEN        101         43       7.32          1
ALLEN        102         22       7.32          2
JONES        101         53        3.6          1

Vous pouvez ensuite pivoter sur ce rnk généré numéro :

with pivot_data as (
  select e.ename, r.room, p.scr,
    sum(d.workhrs) over (partition by e.ename) as wrkhrs,
    rank() over (partition by e.ename order by r.room, p.scr) as rnk
  from productivity p
  join productivityd d on d.productivityid = p.productivityid
  join emp e on e.empno=p.employeeid
  join rooms r on r.id = p.roomid
)
select *
from   pivot_data
pivot (
  min(room) as room, min(scr) as scr  --<-- pivot_clause
  for rnk                             --<-- pivot_for_clause        
  in  (1, 2, 3)                       --<-- pivot_in_clause         
);

ENAME     WRKHRS     1_ROOM      1_SCR     2_ROOM      2_SCR     3_ROOM      3_SCR
----- ---------- ---------- ---------- ---------- ---------- ---------- ----------
ALLEN       7.32        101         43        102         22                      
JONES        3.6        101         53                                            

Vous devez connaître le nombre maximum de chambres qu'un employé peut avoir - c'est-à-dire le rnk le plus élevé pourrait jamais être - et incluez tous ceux dans le in clause. Ce qui signifie que vous risquez de vous retrouver avec des colonnes vides, comme dans cet exemple où il n'y a pas de données pour 3_room ou 3_scr . Vous ne pouvez pas éviter cela, sauf si vous obtenez un résultat XML ou générez la requête dynamiquement.