Kiedy próbujesz przestawić dynamiczną lub nieznaną wartość, zawsze sugeruję, aby najpierw zacząć od statycznej lub zakodowanej wersji zapytania, a następnie przekonwertować ją na dynamiczny SQL.
MySQL nie posiada funkcji PIVOT, więc aby uzyskać wynik, musisz użyć funkcji agregującej z wyrażeniem CASE. Statyczna wersja kodu będzie podobna do następującej:
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;
Zobacz Skrzypce SQL z wersją demonstracyjną .
Teraz, jeśli będziesz mieć nieznaną liczbę keynames
które chcesz przekonwertować na kolumny, musisz użyć przygotowane oświadczenie
do generowania dynamicznego SQL. Kod będzie podobny do:
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;
Zobacz Skrzypce SQL z wersją demonstracyjną .
Należy pamiętać o GROUP_CONCAT
funkcja do tworzenia ciągu kolumn ma domyślną maksymalną długość 1024, więc jeśli zamierzasz mieć dużo znaków w tym ciągu, być może będziesz musiał zmienić wartość sesji dla group_concat_max_len
.
To zapytanie da wynik:
| TEAMID | TEAMNAME | PROCESSID | PROCESSNAME | SHAPE | VEGETABLE | FRUIT | ANIMAL |
| 1 | teamA | 1 | processA | circle | carrot | apple | (null) |
| 1 | teamA | 2 | processB | (null) | (null) | (null) | dog |