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

Permintaan PHP dan MySQL, gunakan PHP untuk mengonversi baris ke kolom

Dimungkinkan untuk mendapatkan hasilnya menggunakan kueri SQL, tetapi itu tidak sepele.

Tetapi sebelum Anda menempuh rute itu, saya sarankan Anda mempertimbangkan pendekatan yang berbeda.

Karena kueri mengembalikan kumpulan baris yang relatif kecil, Anda dapat mengambil seluruh kumpulan hasil ke dalam PHP sebagai larik dua dimensi.

Perhatikan kasus yang cukup sederhana, sebagai ilustrasi:

SELECT foo, fee, fi, fo, fum
  FROM mytable 
 ORDER BY foo

foo fee fi  fo  fum
--- --- --- --- ---
ABC   2   3   5   7
DEF  11  13  17  19

Kita bisa melakukan fetchAll, dan mendapatkan array dua dimensi, lalu mengulang array dan mengambil nilai berdasarkan kolom, bukan berdasarkan baris. Salah satu opsi adalah mengubah array yang kita terima menjadi array baru yang terlihat seperti ini:

bar  ABC  DEF
---  ---  ---
fee    2   11
fi     3   13
fo     5   17
fum    7   19

Sebenarnya tidak perlu melakukan transformasi, Anda bisa menjalankan array asli. Tetapi memisahkan transformasi sebagai langkah terpisah mungkin akan membuat kode Anda sedikit lebih mudah, ketika Anda benar-benar menghasilkan output ke dalam halaman. (Sepertinya masalah yang cukup umum bahwa seseorang mungkin telah menulis fungsi yang melakukan transformasi array yang Anda inginkan. Saya tidak berpikir ada PHP bawaan yang melakukannya.

judul:

array { [0]=>'bar'  [1]=>'ABC'  [2]=>'DEF' }

baris:

array {
  [0]=>array { [0]=>'fee'   [1]=>'2'  [2]=>'11' }
  [1]=>array { [0]=>'fi'    [1]=>'3'  [2]=>'13' }
  [2]=>array { [0]=>'fo'    [1]=>'5'  [2]=>'17' }
  [3]=>array { [0]=>'fum'   [1]=>'7'  [2]=>'19' }
}

Untuk sekumpulan kecil baris seperti yang Anda miliki, saya akan memilih untuk melakukan ini di PHP daripada di SQL.

Tetapi Anda bertanya bagaimana melakukannya dalam SQL. Seperti yang saya katakan sebelumnya, itu tidak sepele.

SQL mengharuskan pernyataan SELECT mendefinisikan setiap kolom yang akan dikembalikan; jumlah dan jenis kolom tidak bisa dinamis ketika pernyataan dijalankan.

Jika kita membuat kueri lain (selain dari kueri asli) yang mendefinisikan kolom, dan mengembalikan baris yang kita harapkan dikembalikan dengan placeholder untuk nilai, kita sudah setengah jalan. Yang tersisa hanyalah melakukan penggabungan luar ke baris yang dikembalikan oleh kueri asli, dan secara kondisional mengembalikan nilai kolom pada baris yang sesuai.

Pendekatan ini berfungsi jika Anda memiliki kumpulan baris dan kolom yang telah ditentukan sebelumnya yang perlu dikembalikan, terutama ketika sumber baris asli jarang, dan kita perlu membuat baris yang "hilang". (Misalnya, mendapatkan jumlah produk yang dipesan, dan ada banyak baris yang hilang, tidak ada cara yang baik untuk menghasilkan baris yang hilang.

Misalnya:

SELECT r.bar
     , '' AS `ABC`
     , '' AS `DEF`
  FROM ( SELECT 'fee' AS bar
          UNION ALL SELECT 'fi'
          UNION ALL SELECT 'fo'
          UNION ALL SELECT 'fum'
       ) r
 GROUP BY r.bar

Itu akan kembali:

 bar  ABC  DEF
 ---  ---  ---
 fee
 fi
 fo
 fum

Jadi, itu membuat kita semua kolom yang ditentukan, dan semua baris yang ingin kita kembalikan. Kolom pertama diisi. Kueri itu belum benar-benar membutuhkan GROUP BY, tetapi kita akan membutuhkannya setelah kita mencocokkan dengan baris dari kumpulan hasil sumber "asli".

"Trik" sekarang adalah mencocokkan baris dari sumber kami, dan mengembalikan nilai dari kolom berdasarkan kondisi yang sesuai.

Apa yang akan kita hasilkan, pada dasarnya adalah kumpulan hasil yang terlihat seperti ini:

bar  foo  ABC  DEF
---  ---  ---  ---
fee  ABC    2
fee  DEF        11
fi   ABC    3
fi   DEF        13
fo   ABC    5
fo   DEF        15
fum  ABC    7
fum  DEF        17

Kemudian kita akan "menciutkan" baris, dengan menghapus kolom foo dari hasil dan melakukan GROUP BY pada bar . Kami akan menggunakan fungsi agregat (baik MAX atau SUM) mengambil keuntungan dari penanganan yang mereka lakukan dengan nilai NULL, untuk menghasilkan hasil seperti ini:

bar  foo  ABC  DEF
---  ---  ---  ---
fee         2   11
fi          3   13
fo          5   15
fum         7   17

Menggunakan SQL yang agak berat ini:

SELECT r.bar
     , MAX(CASE WHEN t.foo = 'ABC' THEN CASE r.bar 
         WHEN 'fee' THEN t.fee 
         WHEN 'fi'  THEN t.fi
         WHEN 'fo'  THEN t.fo
         WHEN 'fum' THEN t.fum
       END END) AS 'ABC'
     , MAX(CASE WHEN t.foo = 'DEF' THEN CASE r.bar 
         WHEN 'fee' THEN t.fee 
         WHEN 'fi'  THEN t.fi
         WHEN 'fo'  THEN t.fo
         WHEN 'fum' THEN t.fum
       END END) AS 'DEF'
  FROM ( SELECT 'foo' AS col
          UNION ALL SELECT 'fee'
          UNION ALL SELECT 'fi'
          UNION ALL SELECT 'fo'
          UNION ALL SELECT 'fum'
       ) r
 CROSS
  JOIN mysource t
 GROUP BY r.bar

Perhatikan bahwa mysource dalam kueri di atas dapat diganti dengan tampilan sebaris, membungkus parens di sekitar kueri yang sesuai yang mengembalikan baris yang kita inginkan.

Tampilan inline alias sebagai r adalah sumber kami untuk mengembalikan baris yang ingin kami kembalikan.

Ekspresi dalam daftar SELECT sedang melakukan pengujian kondisional, untuk memilih nilai yang tepat untuk setiap kolom di setiap baris.

Mengingat pola reguler dari pernyataan CASE, dimungkinkan untuk menggunakan beberapa SQL untuk membantu menghasilkan kueri, tetapi itu harus dilakukan sebagai langkah terpisah. Keluaran dari SQL tersebut dapat digunakan untuk membantu membentuk kueri aktual yang kita butuhkan.

Dalam kasus Anda, mengingat workdate adalah apa yang ingin Anda gunakan untuk tajuk kolom, ini kemungkinan harus dibuat secara dinamis. (Anda dapat menghapus kolom 'hari dalam seminggu' kolom kedua dari kueri sumber asli, dan memindahkannya ke kueri luar.

Jika saya tidak tahu workdate nilai untuk judul sebelum saya menjalankan kueri, maka saya akan memilih untuk membuat TABEL SEMENTARA dan mengisinya dengan hasil dari kueri asli, lalu kueri tabel sementara, untuk mendapatkan workdate header, dan "kolom pertama" untuk menghasilkan baris. Kemudian saya akan menjalankan kueri aktual terhadap tabel sementara.

Untuk mengulangi, saya pikir Anda akan lebih baik melakukan transformasi/poros hasil dari kueri asli Anda di PHP, daripada mencoba melakukannya di SQL.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Kotak kombo WPF mengisi data dari database mysql

  2. Bagaimana memilih dari nama tabel dinamis

  3. Berapa ukuran maksimum database MySQL di versi 5 dan lebih tinggi?

  4. Masukkan Tanggal ke MySql menggunakan c#

  5. Rentang kendala kolom MySQL numerik:bagaimana?