Lorsque vous essayez de faire pivoter une valeur dynamique ou inconnue, je vous suggère toujours de commencer par une version statique ou codée en dur de la requête, puis de la convertir en SQL dynamique.
MySQL n'a pas de fonction PIVOT, vous devrez donc utiliser une fonction d'agrégation avec une expression CASE pour obtenir le résultat. La version statique du code ressemblera à ce qui suit :
select t.id teamid,
t.name teamname,
p.id processid,
p.name processname,
max(case when pd.keyname = 'shape' then tpd.value end) shape,
max(case when pd.keyname = 'vegetable' then tpd.value end) vegetable,
max(case when pd.keyname = 'fruit' then tpd.value end) fruit,
max(case when pd.keyname = 'animal' then tpd.value end) animal
from teams t
inner join teamprocesses tp
on t.id = tp.teamid
inner join TeamProcessDetails tpd
on tp.id = tpd.teamProcessId
inner join processes p
on tp.processid = p.id
inner join processdetails pd
on p.id = pd.processid
and tpd.processDetailsid = pd.id
group by t.id, t.name, p.id, p.name;
Voir SQL Fiddle avec démo .
Maintenant, si vous allez avoir un nombre inconnu de keynames
que vous souhaitez convertir en colonnes, vous devrez alors utiliser un déclaration préparée
pour générer du SQL dynamique. Le code ressemblera à :
SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'max(case when pd.keyname = ''',
keyname,
''' then tpd.value end) AS ',
replace(keyname, ' ', '')
)
) INTO @sql
from ProcessDetails;
SET @sql
= CONCAT('SELECT t.id teamid,
t.name teamname,
p.id processid,
p.name processname, ', @sql, '
from teams t
inner join teamprocesses tp
on t.id = tp.teamid
inner join TeamProcessDetails tpd
on tp.id = tpd.teamProcessId
inner join processes p
on tp.processid = p.id
inner join processdetails pd
on p.id = pd.processid
and tpd.processDetailsid = pd.id
group by t.id, t.name, p.id, p.name;');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Voir SQL Fiddle avec démo .
Une chose à garder à l'esprit le GROUP_CONCAT
la fonction pour créer la chaîne de colonnes a une longueur maximale par défaut de 1024, donc si vous allez avoir beaucoup de caractères dans cette chaîne, vous devrez peut-être modifier la valeur de session pour le group_concat_max_len
.
Cette requête donnera un résultat :
| TEAMID | TEAMNAME | PROCESSID | PROCESSNAME | SHAPE | VEGETABLE | FRUIT | ANIMAL |
| 1 | teamA | 1 | processA | circle | carrot | apple | (null) |
| 1 | teamA | 2 | processB | (null) | (null) | (null) | dog |