Diberikan dua tabel dengan jumlah baris yang tidak ditentukan dengan nama dan nilai, bagaimana saya akan menampilkan pivot CROSS JOIN
dari fungsi di atas nilainya.
CREATE TEMP TABLE foo AS
SELECT x::text AS name, x::int
FROM generate_series(1,10) AS t(x);
CREATE TEMP TABLE bar AS
SELECT x::text AS name, x::int
FROM generate_series(1,5) AS t(x);
Misalnya, jika fungsi itu adalah perkalian, bagaimana saya menghasilkan tabel (perkalian) seperti di bawah ini,
Semua (arg1,arg2,result)
baris tersebut dapat dibuat dengan
SELECT foo.name AS arg1, bar.name AS arg2, foo.x*bar.x AS result
FROM foo
CROSS JOIN bar;
Jadi ini hanya masalah presentasi, saya ingin ini juga bekerja dengan nama kustom - nama yang tidak hanya argumen CAST
ed ke teks tetapi diatur dalam tabel,
CREATE TEMP TABLE foo AS
SELECT chr(x+64) AS name, x::int
FROM generate_series(1,10) AS t(x);
CREATE TEMP TABLE bar AS
SELECT chr(x+72) AS name, x::int
FROM generate_series(1,5) AS t(x);
Saya pikir ini akan mudah dilakukan dengan CROSSTAB yang mampu tipe kembali yang dinamis.
SELECT * FROM crosstab(
'
SELECT foo.x AS arg1, bar.x AS arg2, foo.x*bar.x
FROM foo
CROSS JOIN bar
', 'SELECT DISTINCT name FROM bar'
) AS **MAGIC**
Tapi, tanpa itu **MAGIC**
, aku mengerti
ERROR: a column definition list is required for functions returning "record" LINE 1: SELECT * FROM crosstab(
Untuk referensi, menggunakan contoh di atas dengan nama ini adalah sesuatu yang lebih seperti apa tablefunc
's crosstab()
keinginan.
SELECT * FROM crosstab(
'
SELECT foo.x AS arg1, bar.x AS arg2, foo.x*bar.x
FROM foo
CROSS JOIN bar
'
) AS t(row int, i int, j int, k int, l int, m int);
Tapi, sekarang kita kembali membuat asumsi tentang konten dan ukuran bar
tabel dalam contoh kita. Jadi jika,
- Tabel panjangnya tidak ditentukan,
- Kemudian cross-join mewakili kubus dimensi yang tidak ditentukan (karena di atas),
- Nama-nama katagori (istilah tabulasi silang) ada di tabel
Apa yang terbaik yang dapat kita lakukan di PostgreSQL tanpa "daftar definisi kolom" untuk menghasilkan presentasi seperti itu?
sumber
Jawaban:
Kasus sederhana, SQL statis
Solusi non-dinamis dengan
crosstab()
untuk kasus sederhana:Saya memesan kolom yang dihasilkan dengan
foo.name
, bukanfoo.x
. Keduanya kebetulan dipilah secara paralel, tapi itu hanya pengaturan sederhana. Pilih urutan pengurutan yang tepat untuk kasus Anda. Sebenarnya nilai dari kolom kedua adalah tidak relevan dalam query ini (bentuk 1-parametercrosstab()
).Kami bahkan tidak perlu
crosstab()
dengan 2 parameter karena tidak ada nilai yang hilang menurut definisi. Lihat:(Anda tetap query crosstab dalam pertanyaan dengan mengganti
foo
denganbar
dalam mengedit kemudian. Ini juga perbaikan query, tetapi terus bekerja dengan nama-nama darifoo
.)Jenis pengembalian tidak dikenal, SQL dinamis
Nama dan tipe kolom tidak boleh dinamis. SQL menuntut untuk mengetahui jumlah, nama, dan jenis kolom yang dihasilkan pada waktu panggilan. Entah dengan deklarasi eksplisit atau dari informasi dalam katalog sistem (Itulah yang terjadi dengan
SELECT * FROM tbl
: Postgres mencari definisi tabel yang terdaftar.)Anda ingin Postgres mendapatkan kolom yang dihasilkan dari data di tabel pengguna. Tidak akan terjadi.
Dengan satu atau lain cara, Anda perlu dua perjalanan pulang pergi ke server. Entah Anda membuat kursor dan kemudian berjalan melewatinya. Atau Anda membuat tabel temp dan kemudian memilihnya. Atau Anda mendaftarkan jenis dan menggunakannya dalam panggilan.
Atau Anda cukup membuat kueri dalam satu langkah dan menjalankannya di langkah berikutnya:
Ini menghasilkan kueri di atas, secara dinamis. Jalankan di langkah berikutnya.
Saya menggunakan dolar-tanda kutip (
$$
) untuk menjaga penanganan kutipan bersarang sederhana. Lihat:quote_ident()
sangat penting untuk menghindari nama kolom yang tidak sah (dan mungkin bertahan terhadap injeksi SQL).Terkait:
sumber
Jika Anda membingkai ini sebagai masalah presentasi, Anda mungkin mempertimbangkan fitur presentasi post-query.
Versi yang lebih baru dari
psql
(9.6) datang dengan\crosstabview
, menunjukkan hasil dalam representasi tab silang tanpa dukungan SQL (karena SQL tidak dapat menghasilkan ini secara langsung, seperti yang disebutkan dalam jawaban @ Erwin: SQL menuntut untuk mengetahui jumlah, nama dan jenis kolom yang dihasilkan pada waktu panggilan )Misalnya, permintaan pertama Anda memberi:
Contoh kedua dengan nama kolom ASCII memberi:
Lihat manual psql dan https://wiki.postgresql.org/wiki/Crosstabview untuk informasi lebih lanjut.
sumber
Ini bukan solusi yang pasti
Ini adalah pendekatan terbaik saya sampai sekarang. Masih perlu mengubah array terakhir menjadi kolom.
Pertama saya mendapatkan produk Cartesian dari kedua tabel:
Tapi, saya telah menambahkan nomor baris hanya untuk mengidentifikasi setiap baris dari tabel pertama.
Maka saya telah menambahkan hasilnya dalam format ini:
Mengubahnya menjadi string yang dibatasi oleh koma:
(Hanya untuk mencobanya nanti: http://rextester.com/NBCYXA2183 )
sumber
Sebagai catatan, sepertinya SQL: 2016 akan mengakomodasi ini dengan fungsi tabel Polymorphic (ISO / IEC TR 19075-7: 2017)
Saya menemukan tautan What's New in SQL: 2016 tetapi penulis tidak mengembangkan sebanyak ini.
sumber