När du försöker pivotera dynamiskt eller okänt värde, skulle jag alltid föreslå att du börjar med en statisk eller hårdkodad version av frågan först och sedan konverterar den till dynamisk SQL.
MySQL har ingen PIVOT-funktion så du måste använda en aggregatfunktion med ett CASE-uttryck för att få resultatet. Den statiska versionen av koden kommer att likna följande:
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;
Se SQL-fiol med demo .
Om du nu ska ha ett okänt antal keynames
som du vill konvertera till kolumner, då måste du använda en förberett uttalande
för att generera dynamisk SQL. Koden kommer att likna:
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;
Se SQL-fiol med demo .
En sak att tänka på GROUP_CONCAT
funktionen för att skapa kolumnsträngen har en standard maxlängd på 1024, så om du ska ha många tecken i denna sträng kanske du måste ändra sessionsvärdet för group_concat_max_len
.
Denna fråga ger ett resultat:
| TEAMID | TEAMNAME | PROCESSID | PROCESSNAME | SHAPE | VEGETABLE | FRUIT | ANIMAL |
| 1 | teamA | 1 | processA | circle | carrot | apple | (null) |
| 1 | teamA | 2 | processB | (null) | (null) | (null) | dog |