Saya akan menambahkan penjelasan yang lebih panjang dan lebih rinci tentang langkah-langkah yang harus diambil untuk menyelesaikan masalah ini. Saya minta maaf jika terlalu panjang.
Saya akan mulai dengan dasar yang Anda berikan dan menggunakannya untuk mendefinisikan beberapa istilah yang akan saya gunakan untuk sisa posting ini. Ini akan menjadi tabel dasar :
select * from history;
+--------+----------+-----------+
| hostid | itemname | itemvalue |
+--------+----------+-----------+
| 1 | A | 10 |
| 1 | B | 3 |
| 2 | A | 9 |
| 2 | C | 40 |
+--------+----------+-----------+
Ini akan menjadi tujuan kami, tabel pivot cantik :
select * from history_itemvalue_pivot;
+--------+------+------+------+
| hostid | A | B | C |
+--------+------+------+------+
| 1 | 10 | 3 | 0 |
| 2 | 9 | 0 | 40 |
+--------+------+------+------+
Nilai dalam history.hostid
kolom akan menjadi nilai-y dalam tabel pivot. Nilai dalam history.itemname
kolom akan menjadi nilai-x (untuk alasan yang jelas).
Ketika saya harus memecahkan masalah membuat tabel pivot, saya mengatasinya menggunakan proses tiga langkah (dengan langkah keempat opsional):
- pilih kolom yang diinginkan, yaitu nilai-y dan nilai-x
- perluas tabel dasar dengan kolom tambahan -- satu untuk setiap nilai-x
- mengelompokkan dan menggabungkan tabel yang diperluas -- satu grup untuk setiap nilai-y
- (opsional) mempercantik tabel gabungan
Mari terapkan langkah-langkah ini untuk masalah Anda dan lihat apa yang kami dapatkan:
Langkah 1:pilih kolom minat . Pada hasil yang diinginkan, hostid
memberikan nilai-y dan itemname
memberikan nilai-x .
Langkah 2:perluas tabel dasar dengan kolom tambahan . Kami biasanya membutuhkan satu kolom per nilai-x. Ingat bahwa kolom nilai-x kita adalah itemname
:
create view history_extended as (
select
history.*,
case when itemname = "A" then itemvalue end as A,
case when itemname = "B" then itemvalue end as B,
case when itemname = "C" then itemvalue end as C
from history
);
select * from history_extended;
+--------+----------+-----------+------+------+------+
| hostid | itemname | itemvalue | A | B | C |
+--------+----------+-----------+------+------+------+
| 1 | A | 10 | 10 | NULL | NULL |
| 1 | B | 3 | NULL | 3 | NULL |
| 2 | A | 9 | 9 | NULL | NULL |
| 2 | C | 40 | NULL | NULL | 40 |
+--------+----------+-----------+------+------+------+
Perhatikan bahwa kami tidak mengubah jumlah baris -- kami hanya menambahkan kolom tambahan. Perhatikan juga pola NULL
s -- satu baris dengan itemname = "A"
memiliki nilai bukan nol untuk kolom baru A
, dan nilai nol untuk kolom baru lainnya.
Langkah 3:kelompokkan dan gabungkan tabel yang diperluas . Kita perlu group by hostid
, karena memberikan nilai-y:
create view history_itemvalue_pivot as (
select
hostid,
sum(A) as A,
sum(B) as B,
sum(C) as C
from history_extended
group by hostid
);
select * from history_itemvalue_pivot;
+--------+------+------+------+
| hostid | A | B | C |
+--------+------+------+------+
| 1 | 10 | 3 | NULL |
| 2 | 9 | NULL | 40 |
+--------+------+------+------+
(Perhatikan bahwa kita sekarang memiliki satu baris per nilai-y.) Oke, kita hampir sampai! Kita hanya perlu menyingkirkan NULL
yang jelek itu s.
Langkah 4:percantik . Kami hanya akan mengganti nilai nol dengan nol sehingga kumpulan hasil lebih bagus untuk dilihat:
create view history_itemvalue_pivot_pretty as (
select
hostid,
coalesce(A, 0) as A,
coalesce(B, 0) as B,
coalesce(C, 0) as C
from history_itemvalue_pivot
);
select * from history_itemvalue_pivot_pretty;
+--------+------+------+------+
| hostid | A | B | C |
+--------+------+------+------+
| 1 | 10 | 3 | 0 |
| 2 | 9 | 0 | 40 |
+--------+------+------+------+
Dan selesai -- kami telah membuat tabel pivot yang bagus dan cantik menggunakan MySQL.
Pertimbangan saat menerapkan prosedur ini:
- nilai apa yang akan digunakan di kolom tambahan. Saya menggunakan
itemvalue
dalam contoh ini - nilai "netral" apa yang akan digunakan di kolom tambahan. Saya menggunakan
NULL
, tetapi bisa juga0
atau""
, tergantung pada situasi Anda sebenarnya - fungsi agregat apa yang digunakan saat mengelompokkan. Saya menggunakan
sum
, tetapicount
danmax
juga sering digunakan (max
sering digunakan saat membangun "objek" satu baris yang telah tersebar di banyak baris) - menggunakan beberapa kolom untuk nilai-y. Solusi ini tidak terbatas pada penggunaan satu kolom untuk nilai-y -- cukup colokkan kolom tambahan ke
group by
klausa (dan jangan lupa untukselect
mereka)
Batasan yang diketahui:
- solusi ini tidak mengizinkan n kolom di tabel pivot -- setiap kolom pivot perlu ditambahkan secara manual saat memperluas tabel dasar. Jadi untuk 5 atau 10 nilai x, solusi ini bagus. Untuk 100, tidak begitu bagus. Ada beberapa solusi dengan prosedur tersimpan yang menghasilkan kueri, tetapi itu jelek dan sulit untuk diperbaiki. Saat ini saya tidak tahu cara yang baik untuk memecahkan masalah ini ketika tabel pivot harus memiliki banyak kolom.