PostgreSQL 左连接查询对象数组聚合

Tom*_*uis 11 sql postgresql json aggregate-functions left-join

我有2张桌子:

table "person" with columns: person_id, person_name
table "pet" with columns: pet_id, owner_id, pet_name

person data:
1, 'John'
2, 'Jill'
3, 'Mary'

pet data:
1, 1, 'Fluffy'
2, 1, 'Buster'
3, 2, 'Doggy'
Run Code Online (Sandbox Code Playgroud)

如何写SELECT查询语句从person左连接petperson_id = owner_id具有聚合函数,所以我的结果数据的样子:

1,[{pet_id:1,pet_name:'Fluffy'},{pet_id:2,pet_name:'Buster'}],'John'
2,[{pet_id:3,pet_name:'Doggy'}],'Jill'
3,[],'Mary'
Run Code Online (Sandbox Code Playgroud)

Erw*_*ter 15

LEFT JOIN LATERAL在子查询中使用和聚合:

SELECT p.person_id, COALESCE(pet.pets, '[]') AS pets, p.person_name
FROM   person p
LEFT   JOIN LATERAL (
   SELECT json_agg(json_build_object('pet_id', pet.pet_id
                                   , 'pet_name', pet.pet_name)) AS pets
   FROM   pet
   WHERE  pet.owner_id = p.person_id
   ) pet ON true
ORDER  BY p.person_id;  -- optional, Q suggests ordered results
Run Code Online (Sandbox Code Playgroud)

db<>在这里摆弄

这样您就不需要聚合来自外部查询的结果。当您的外部查询比问题中的示例更复杂时,更简单、更清晰。当聚合多个相关表时,它甚至成为一种必需品:

当外部表上有谓词时,它通常也会快得多person——这是典型的用例。

确保有一个指标pet(owner_id),使之快。或者甚至在pet(owner_id, pet_id, pet_name)(或pet(owner_id) INCLUDE (pet_id, pet_name)在 Postgres 11 或更高版本中)如果您的行不宽,就像在您的示例中一样,并且您从中获得仅索引扫描。

哦,json_build_object()用于保留任意选择的属性名称

有关的:


kli*_*lin 8

select
    person_id,
    jsonb_agg(to_jsonb(pet) - 'owner_id'),
    person_name
from person
left join pet on person_id = owner_id
group by person_id;

 person_id |                                 jsonb_agg                                  | person_name 
-----------+----------------------------------------------------------------------------+-------------
         1 | [{"pet_id": 1, "pet_name": "Fluffy"}, {"pet_id": 2, "pet_name": "Buster"}] | John
         2 | [{"pet_id": 3, "pet_name": "Doggy"}]                                       | Jill
         3 | [null]                                                                     | Mary
(3 rows)
Run Code Online (Sandbox Code Playgroud)

Db<>小提琴。