Sayangnya, tidak ada ketentuan dalam sintaks SQL untuk mengatakan "semua kolom kecuali kolom yang satu ini" . Anda dapat mencapai tujuan Anda dengan mengeja daftar kolom yang tersisa dalam ekspresi tipe baris :
SELECT a.id, a.name
, json_agg((b.col1, b.col2, b.col3)) AS item
FROM a
JOIN b ON b.item_id = a.id
GROUP BY a.id, a.name;
Itu pendek untuk bentuk yang lebih eksplisit: . ROW
(b.col1, b.col2, b.col3)
Namun, nama kolom tidak dipertahankan dalam ekspresi tipe baris. Anda mendapatkan nama kunci umum dalam objek JSON dengan cara ini. Saya melihat 3 opsi untuk mempertahankan nama kolom asli:
1. Pilih tipe yang terdaftar
Pilih tipe baris yang terkenal (terdaftar). Suatu tipe terdaftar untuk setiap tabel atau tampilan yang ada atau dengan CREATE TYPE
pernyataan eksplisit . Anda mungkin menggunakan tabel sementara untuk solusi ad-hoc (berlaku selama durasi sesi):
CREATE TEMP TABLE x (col1 int, col2 text, col3 date); -- use adequate data types!
SELECT a.id, a.name
, json_agg((b.col1, b.col2, b.col3)::x) AS item
FROM a
JOIN b ON b.item_id = a.id
GROUP BY a.id, a.name;
2. Gunakan subselect
Gunakan subselect untuk membangun tabel turunan dan referensi tabel secara keseluruhan . Ini juga membawa nama kolom. Ini lebih bertele-tele, tetapi Anda tidak perlu tipe terdaftar:
SELECT a.id, a.name
, json_agg((SELECT x FROM (SELECT b.col1, b.col2, b.col3) AS x)) AS item
FROM a
JOIN b ON b.item_id = a.id
GROUP BY a.id, a.name;
SELECT a.id, a.name
, json_agg(json_build_object('col1', b.col1, 'col2', b.col2, 'col3', b.col3)) AS item
FROM a
JOIN b ON b.item_id = a.id
GROUP BY a.id, a.name;
Terkait:
Mirip untuk jsonb
masing-masing fungsi jsonb_agg()
dan jsonb_build_object()
.
Untuk Postgres 9.5 atau yang lebih baru, lihat juga jawaban a_horse dengan varian sintaks baru yang lebih pendek: Postgres menambahkan operator minus -
untukjsonb
mengatakan "semua kunci kecuali kunci yang satu ini" .
Karena Postgres 10 "kecuali beberapa kunci" diimplementasikan dengan operator yang sama dengan text[]
mlt seperti - operan 2 berkomentar.
Mulai dengan 9.6 yang bisa Anda gunakan
-
untuk menghapus kunci dari JSONB:to_jsonb(b)
akan mengonversi seluruh baris dan- 'item_id'
kemudian akan menghapus kunci dengan namaitem_id
hasil yang kemudian dikumpulkan.sumber
json_agg
fungsi:function json_agg(record) does not exist
Anda sebenarnya dapat melakukannya tanpa grup dengan, menggunakan subqueries
kembali
Artikel dari John Atten ini sangat menarik dan memiliki lebih banyak detail
sumber
Saya telah menemukan bahwa yang terbaik untuk membuat JSON, kemudian mengumpulkannya. misalnya
Perhatikan ini dapat dilakukan sebagai subquery jika Anda tidak menyukai CTE (atau memiliki masalah kinerja karena menggunakannya).
Perhatikan juga, jika Anda akan sering melakukan ini, mungkin bermanfaat untuk membuat fungsi untuk membungkus pasangan nilai kunci untuk Anda sehingga kode terlihat lebih bersih. Anda akan melewati fungsi Anda (misalnya)
'ecks', 'x'
dan itu akan kembali"ecks": "x"
.sumber
Meskipun masih tidak ada cara untuk melakukan apa pun tentang memilih semua kolom kecuali satu bit, tetapi Anda dapat menggunakan
json_agg(to_json(b.col_1, b.col_2, b.col_3 ...))
untuk mendapatkan json array dari jsons masing-masing dalam format{"col_1":"col_1 value", ...}
.Jadi kueri akan terlihat seperti:
dan akan mengembalikan baris sebagai:
(Saya menggunakan Postgres 9.5.3 sekarang dan tidak 100% yakin kapan dukungan ini ditambahkan.)
sumber
Anda bisa menggunakan
json_build_object
seperti inisumber