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'
如何写SELECT查询语句从person左连接pet上person_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'
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
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()用于保留任意选择的属性名称:
有关的:
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)
| 归档时间: | 
 | 
| 查看次数: | 4439 次 | 
| 最近记录: |