Saat Anda mencoba untuk memutar nilai dinamis atau tidak dikenal, saya selalu menyarankan agar Anda memulai dengan kueri versi statis atau hard-code terlebih dahulu, lalu mengonversinya menjadi SQL dinamis.
MySQL tidak memiliki fungsi PIVOT sehingga Anda perlu menggunakan fungsi agregat dengan ekspresi CASE untuk mendapatkan hasilnya. Versi statis dari kode akan mirip dengan berikut ini:
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;
Lihat SQL Fiddle dengan Demo .
Sekarang jika Anda akan memiliki jumlah keynames
yang tidak diketahui yang ingin Anda ubah menjadi kolom, maka Anda harus menggunakan pernyataan yang disiapkan
untuk menghasilkan SQL dinamis. Kodenya akan mirip dengan:
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;
Lihat SQL Fiddle dengan Demo .
Satu hal yang perlu diingat GROUP_CONCAT
fungsi untuk membuat string kolom memiliki panjang maksimum default 1024, jadi jika Anda akan memiliki banyak karakter dalam string ini, Anda mungkin harus mengubah nilai sesi untuk group_concat_max_len
.
Kueri ini akan memberikan hasil:
| TEAMID | TEAMNAME | PROCESSID | PROCESSNAME | SHAPE | VEGETABLE | FRUIT | ANIMAL |
| 1 | teamA | 1 | processA | circle | carrot | apple | (null) |
| 1 | teamA | 2 | processB | (null) | (null) | (null) | dog |