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

masalah dengan tabel pivot mysql

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 |



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jenis konflik MySqlParameter saat menggunakan Entity Framework dengan Pomelo

  2. Mysql/InnoDB berhenti bekerja di Linode Server

  3. Kueri SQL untuk mencocokkan penjual dan pembeli

  4. Menggunakan ALTER untuk menjatuhkan kolom jika ada di MySQL

  5. Logstash tidak membaca entri baru dari MySQL