Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

MySQL - Baris ke Kolom

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):

  1. pilih kolom yang diinginkan, yaitu nilai-y dan nilai-x
  2. perluas tabel dasar dengan kolom tambahan -- satu untuk setiap nilai-x
  3. mengelompokkan dan menggabungkan tabel yang diperluas -- satu grup untuk setiap nilai-y
  4. (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 juga 0 atau "" , tergantung pada situasi Anda sebenarnya
  • fungsi agregat apa yang digunakan saat mengelompokkan. Saya menggunakan sum , tetapi count dan max 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 untuk select 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.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Apakah ada Profiler yang setara untuk MySql?

  2. Cara terbaik untuk memeriksa apakah mysql_query mengembalikan hasil apa pun?

  3. Sintaks SQL CREATE TABLE – Didaftarkan oleh DBMS

  4. Akses root MySQL dari semua host

  5. Cara Memantau Database MySQL/MariaDB menggunakan Netdata di CentOS 7