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左连接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'
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()用于保留任意选择的属性名称:
有关的:
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)
| 归档时间: |
|
| 查看次数: |
4439 次 |
| 最近记录: |