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.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 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, hostid
menyediakan y-nilai dan itemname
menyediakan 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 NULL
s - 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 NULL
itu.
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
itemvalue
contoh ini
- apa nilai "netral" untuk digunakan dalam kolom tambahan. Saya menggunakan
NULL
, tetapi bisa juga 0
atau ""
, tergantung pada situasi Anda yang sebenarnya
- fungsi agregat apa yang digunakan saat pengelompokan. Saya menggunakan
sum
, tetapi count
dan max
juga 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 by
klausa (dan jangan lupa untuk select
itu)
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.