PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Menggunakan row_to_json() dengan gabungan bersarang

Pembaruan:Di PostgreSQL 9.4 ini meningkat pesat dengan pengenalan to_json , json_build_object , json_object dan json_build_array , meskipun bertele-tele karena kebutuhan untuk menamai semua bidang secara eksplisit:

select
        json_build_object(
                'id', u.id,
                'name', u.name,
                'email', u.email,
                'user_role_id', u.user_role_id,
                'user_role', json_build_object(
                        'id', ur.id,
                        'name', ur.name,
                        'description', ur.description,
                        'duty_id', ur.duty_id,
                        'duty', json_build_object(
                                'id', d.id,
                                'name', d.name
                        )
                )
    )
from users u
inner join user_roles ur on ur.id = u.user_role_id
inner join role_duties d on d.id = ur.duty_id;

Untuk versi yang lebih lama, baca terus.

Itu tidak terbatas pada satu baris, itu hanya sedikit menyakitkan. Anda tidak dapat membuat alias tipe baris komposit menggunakan AS , jadi Anda perlu menggunakan ekspresi subquery alias atau CTE untuk mendapatkan efeknya:

select row_to_json(row)
from (
    select u.*, urd AS user_role
    from users u
    inner join (
        select ur.*, d
        from user_roles ur
        inner join role_duties d on d.id = ur.duty_id
    ) urd(id,name,description,duty_id,duty) on urd.id = u.user_role_id
) row;

menghasilkan, melalui http://jsonprettyprint.com/:

{
  "id": 1,
  "name": "Dan",
  "email": "[email protected]",
  "user_role_id": 1,
  "user_role": {
    "id": 1,
    "name": "admin",
    "description": "Administrative duties in the system",
    "duty_id": 1,
    "duty": {
      "id": 1,
      "name": "Script Execution"
    }
  }
}

Anda akan ingin menggunakan array_to_json(array_agg(...)) ketika Anda memiliki hubungan 1:banyak, btw.

Kueri di atas idealnya dapat ditulis sebagai:

select row_to_json(
    ROW(u.*, ROW(ur.*, d AS duty) AS user_role)
)
from users u
inner join user_roles ur on ur.id = u.user_role_id
inner join role_duties d on d.id = ur.duty_id;

... tetapi ROW PostgreSQL konstruktor tidak menerima AS alias kolom. Sayangnya.

Untungnya, mereka mengoptimalkan hal yang sama. Bandingkan paketnya:

  • Versi subkueri bersarang; vs
  • Yang terakhir bersarang ROW versi konstruktor dengan alias dihapus sehingga dijalankan

Karena CTE adalah pagar pengoptimalan, frasa ulang versi subkueri bersarang untuk menggunakan CTE berantai (WITH ekspresi) mungkin tidak berfungsi dengan baik, dan tidak akan menghasilkan rencana yang sama. Dalam hal ini Anda agak terjebak dengan subkueri bersarang jelek sampai kami mendapatkan beberapa peningkatan pada row_to_json atau cara untuk mengganti nama kolom dalam ROW konstruktor secara lebih langsung.

Bagaimanapun, secara umum, prinsipnya adalah di mana Anda ingin membuat objek json dengan kolom a, b, c , dan Anda ingin menulis sintaks ilegal:

ROW(a, b, c) AS outername(name1, name2, name3)

Anda dapat menggunakan subkueri skalar yang mengembalikan nilai yang diketik baris:

(SELECT x FROM (SELECT a AS name1, b AS name2, c AS name3) x) AS outername

Atau:

(SELECT x FROM (SELECT a, b, c) AS x(name1, name2, name3)) AS outername

Selain itu, perlu diingat bahwa Anda dapat membuat json nilai tanpa kutipan tambahan, mis. jika Anda memasukkan output dari json_agg dalam row_to_json , json_agg bagian dalam hasilnya tidak akan dikutip sebagai string, itu akan dimasukkan langsung sebagai json.

misalnya dalam contoh arbitrer:

SELECT row_to_json(
        (SELECT x FROM (SELECT
                1 AS k1,
                2 AS k2,
                (SELECT json_agg( (SELECT x FROM (SELECT 1 AS a, 2 AS b) x) )
                 FROM generate_series(1,2) ) AS k3
        ) x),
        true
);

outputnya adalah:

{"k1":1,
 "k2":2,
 "k3":[{"a":1,"b":2}, 
 {"a":1,"b":2}]}

Perhatikan bahwa json_agg produk, [{"a":1,"b":2}, {"a":1,"b":2}] , belum di-escape lagi, sebagai text akan.

Ini berarti Anda dapat menciptakan json untuk membuat baris, Anda tidak selalu harus membuat tipe komposit PostgreSQL yang sangat kompleks, lalu panggil row_to_json pada keluaran.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Memberitahu Pengguna Anda untuk Melakukan Fork Sendiri

  2. Peningkatan Otomatis PostgreSQL

  3. Bagaimana cara membuat enum Java &Postgres bekerja sama untuk pembaruan?

  4. Kembalikan Daftar Zona Waktu yang Didukung oleh PostgreSQL

  5. postgres pengguna meluncurkan proses yang menggunakan semua CPU 100% penggunaan