Saya akan menambahkan penjelasan yang agak lebih panjang dan lebih rinci tentang langkah yang harus diambil untuk menyelesaikan masalah ini. Saya minta maaf jika terlalu lama.
Saya akan mulai dengan pangkalan yang Anda berikan dan menggunakannya untuk menentukan 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.hostidkolom akan menjadi nilai-y dalam tabel pivot. Nilai dalam history.itemnamekolom akan menjadi nilai x (untuk alasan yang jelas).
Ketika saya harus menyelesaikan masalah membuat tabel pivot, saya mengatasinya menggunakan proses tiga langkah (dengan langkah keempat opsional):
- pilih kolom yang diminati, yaitu nilai-y dan x
- memperpanjang tabel dasar dengan kolom tambahan - satu untuk masing-masing nilai x
- kelompokkan dan agregat tabel diperpanjang - satu kelompok untuk masing-masing nilai-y
- (opsional) cantikkan tabel agregat
Mari kita terapkan langkah-langkah ini untuk masalah Anda dan lihat apa yang kami dapatkan:
Langkah 1: pilih kolom yang diminati . Dalam hasil yang diinginkan, hostidmenyediakan y-nilai dan itemnamemenyediakan x-nilai .
Langkah 2: perpanjang tabel dasar dengan kolom tambahan . Kami biasanya membutuhkan satu kolom per nilai x. Ingat bahwa kolom x-value kami 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 baru saja menambahkan kolom tambahan. Perhatikan juga pola NULLs - baris dengan itemname = "A"nilai bukan nol untuk kolom baruA , dan nilai nol untuk kolom baru lainnya.
Langkah 3: kelompokkan dan agregat tabel diperpanjang . 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 yang jelek NULLitu.
Langkah 4: cantikkan . Kami hanya akan mengganti nilai nol dengan nol sehingga set hasil lebih baik 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 kami selesai - kami telah membangun tabel pivot yang bagus dan cantik menggunakan MySQL.
Pertimbangan saat menerapkan prosedur ini:
- nilai apa yang digunakan di kolom tambahan. Saya menggunakan
itemvaluecontoh ini
- apa nilai "netral" untuk digunakan dalam kolom tambahan. Saya menggunakan
NULL, tetapi bisa juga 0atau "", tergantung pada situasi Anda yang sebenarnya
- fungsi agregat apa yang digunakan saat pengelompokan. Saya menggunakan
sum, tetapi countdan maxjuga sering digunakan (max sering digunakan ketika membangun "objek" satu baris yang telah tersebar di banyak baris)
- menggunakan beberapa kolom untuk nilai-y. Solusi ini tidak terbatas pada menggunakan satu kolom untuk nilai-y - cukup tancapkan kolom tambahan ke
group byklausa (dan jangan lupa untuk selectitu)
Keterbatasan yang diketahui:
- solusi ini tidak mengizinkan n kolom dalam 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 baik. Ada beberapa solusi dengan prosedur tersimpan menghasilkan kueri, tetapi mereka jelek dan sulit untuk diperbaiki. Saat ini saya tidak tahu cara yang baik untuk menyelesaikan masalah ini ketika tabel pivot perlu memiliki banyak kolom.