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.