TL; DR
SELECT json_agg(t) FROM t
untuk larik objek JSON, dan
SELECT
json_build_object(
'a', json_agg(t.a),
'b', json_agg(t.b)
)
FROM t
untuk objek array JSON.
Daftar objek
Bagian ini menjelaskan cara membuat larik objek JSON, dengan setiap baris diubah menjadi satu objek. Hasilnya terlihat seperti ini:
[{"a":1,"b":"value1"},{"a":2,"b":"value2"},{"a":3,"b":"value3"}]
9.3 dan lebih tinggi
The json_agg
Fungsi menghasilkan hasil ini keluar dari kotak. Ini secara otomatis mencari cara untuk mengubah inputnya menjadi JSON dan menggabungkannya menjadi sebuah array.
SELECT json_agg(t) FROM t
Tidak ada jsonb
(diperkenalkan pada 9.4) versi json_agg
. Anda dapat menggabungkan baris menjadi array dan kemudian mengonversinya:
SELECT to_jsonb(array_agg(t)) FROM t
atau gabungkan json_agg
dengan pemeran:
SELECT json_agg(t)::jsonb FROM t
Pengujian saya menunjukkan bahwa menggabungkan mereka ke dalam array terlebih dahulu sedikit lebih cepat. Saya menduga bahwa ini karena pemeran harus mengurai seluruh hasil JSON.
9.2
9.2 tidak memiliki json_agg
atau to_json
fungsi, jadi Anda perlu menggunakan yang lebih lama array_to_json
:
SELECT array_to_json(array_agg(t)) FROM t
Anda secara opsional dapat menyertakan row_to_json
panggilan dalam kueri:
SELECT array_to_json(array_agg(row_to_json(t))) FROM t
Ini mengonversi setiap baris menjadi objek JSON, menggabungkan objek JSON sebagai larik, lalu mengonversi larik menjadi larik JSON.
Saya tidak dapat melihat perbedaan kinerja yang signifikan antara keduanya.
Objek daftar
Bagian ini menjelaskan cara membuat objek JSON, dengan setiap kunci menjadi kolom di tabel dan setiap nilai menjadi larik nilai kolom. Hasilnya terlihat seperti ini:
{"a":[1,2,3], "b":["value1","value2","value3"]}
9.5 dan lebih tinggi
Kami dapat memanfaatkan json_build_object
fungsinya:
SELECT
json_build_object(
'a', json_agg(t.a),
'b', json_agg(t.b)
)
FROM t
Anda juga bisa menggabungkan kolom, membuat satu baris, lalu mengubahnya menjadi objek:
SELECT to_json(r)
FROM (
SELECT
json_agg(t.a) AS a,
json_agg(t.b) AS b
FROM t
) r
Perhatikan bahwa aliasing array mutlak diperlukan untuk memastikan bahwa objek memiliki nama yang diinginkan.
Mana yang lebih jelas adalah soal opini. Jika menggunakanjson_build_object
fungsi ini, saya sangat menyarankan untuk meletakkan satu pasangan kunci / nilai pada satu baris untuk meningkatkan keterbacaan.
Anda juga bisa menggunakan array_agg
sebagai pengganti json_agg
, tetapi pengujian saya menunjukkan bahwa json_agg
sedikit lebih cepat.
Tidak ada jsonb
versi dari json_build_object
fungsi tersebut. Anda dapat menggabungkan menjadi satu baris dan mengonversi:
SELECT to_jsonb(r)
FROM (
SELECT
array_agg(t.a) AS a,
array_agg(t.b) AS b
FROM t
) r
Berbeda dengan query lain untuk jenis hasil ini, array_agg
sepertinya menjadi sedikit lebih cepat saat digunakan to_jsonb
. Saya menduga ini karena penguraian overhead dan memvalidasi hasil JSON dari json_agg
.
Atau Anda dapat menggunakan pemeran eksplisit:
SELECT
json_build_object(
'a', json_agg(t.a),
'b', json_agg(t.b)
)::jsonb
FROM t
The to_jsonb
Versi memungkinkan Anda untuk menghindari pemain dan lebih cepat, menurut pengujian saya; sekali lagi, saya menduga ini karena overhead parsing dan memvalidasi hasilnya.
9.4 dan 9.3
The json_build_object
fungsi baru untuk 9,5, sehingga Anda harus agregat dan mengkonversi ke objek di versi sebelumnya:
SELECT to_json(r)
FROM (
SELECT
json_agg(t.a) AS a,
json_agg(t.b) AS b
FROM t
) r
atau
SELECT to_jsonb(r)
FROM (
SELECT
array_agg(t.a) AS a,
array_agg(t.b) AS b
FROM t
) r
tergantung pada apakah Anda ingin json
atau jsonb
.
(9.3 tidak memiliki jsonb
.)
9.2
Di 9.2, bahkan tidak to_json
ada. Anda harus menggunakan row_to_json
:
SELECT row_to_json(r)
FROM (
SELECT
array_agg(t.a) AS a,
array_agg(t.b) AS b
FROM t
) r
Dokumentasi
Temukan dokumentasi untuk fungsi JSON dalam fungsi JSON .
json_agg
ada di halaman fungsi agregat .
Rancangan
Jika kinerja itu penting, pastikan Anda mengukur kueri Anda terhadap skema dan data Anda sendiri, daripada mempercayai pengujian saya.
Apakah itu desain yang bagus atau tidak sangat tergantung pada aplikasi spesifik Anda. Dalam hal pemeliharaan, saya tidak melihat ada masalah khusus. Ini menyederhanakan kode aplikasi Anda dan berarti lebih sedikit yang harus dipertahankan di bagian aplikasi tersebut. Jika PG dapat memberikan hasil yang Anda butuhkan di luar kotak, satu-satunya alasan yang dapat saya pikirkan untuk tidak menggunakannya adalah pertimbangan kinerja. Jangan menemukan kembali roda dan semuanya.
Nulls
Fungsi agregat biasanya memberikan kembali NULL
ketika mereka beroperasi pada baris nol. Jika ini adalah kemungkinan, Anda mungkin ingin menggunakan COALESCE
untuk menghindarinya. Beberapa contoh:
SELECT COALESCE(json_agg(t), '[]'::json) FROM t
Atau
SELECT to_jsonb(COALESCE(array_agg(t), ARRAY[]::t[])) FROM t
Kredit ke Hannes Landeholm untuk menunjukkan ini