我使用以下架构:
CREATE TABLE person (
person_name VARCHAR PRIMARY KEY
);
CREATE TABLE pet (
animal_name VARCHAR,
person_name VARCHAR REFERENCES person(person_name),
PRIMARY KEY (animal_name, person_name)
);
我希望创建一个表格,对于每个person_name
,我会得到一个包含该人宠物的数组。我正在使用 PostgreSQL 9.3.4 。
我在每个表中都有以下值:
人
PERSON_NAME
-----------
Alice
Bob
宠物
ANIMAL_NAME | PERSON_NAME
-------------------------
Woof | Alice
Meow | Alice
我希望创建下表:
PERSON_NAME | PETS
--------------------------
Alice | {Woof, Meow}
Bob | {}
但是,我无法创建空数组。我得到的是以下内容:
PERSON_NAME | PETS
--------------------------
Alice | {Woof, Meow}
Bob | {NULL}
这是我正在使用的查询:
SELECT
person.person_name,
array_agg(pet.animal_name) AS pets
FROM
person LEFT JOIN pet ON person.person_name = pet.person_name
GROUP BY
person.person_name
;
我理解为什么我在内部使用NULL
值获取数组,我想知道如何获得一个空数组。
这是一个fiddle,其中包含创建架构,插入值以及我正在使用的查询所需的代码。网站上显示的结果并未显示NULL
值,尽管它已存在。
修改
结果将被解析为JSON,这就是为什么{NULL}
不是可接受的结果,因为它将被解析为[null]
,这与我要求的[]
不同。出于同样的原因,{""}
之类的东西也不是可接受的结果。
答案 0 :(得分:2)
有两种可能性浮现在脑海中。
一个选项是UNION。
select person.person_name, array_agg(pet.animal_name) as pets
from person
join pet on person.person_name = pet.person_name
group by person.person_name
union
select person.person_name, array[]::text[] as pets
from person
left join pet on person.person_name = pet.person_name
where pet.animal_name is null
第一部分使用JOIN来吸引有宠物的人,然后第二部分抓住那些根本没有宠物的穷人。通过分离它们,您可以为无宠物的人提供一个文字空数组。
另一种选择是使用LEFT JOIN对派生表执行几乎相同的操作:
with pet_names as (
select person.person_name, array_agg(pet.animal_name) as pets
from person
join pet on person.person_name = pet.person_name
group by person.person_name
)
select p.person_name, coalesce(n.pets, array[]::text[])
from person p
left join pet_names n on p.person_name = n.person_name
这个对我来说更自然一点,因为它可以让你使用COALESCE(你想要将NULL映射到其他东西的第一件事)来提供空数组。
更新了演示:http://sqlfiddle.com/#!15/24ccc/7
可能还有其他解决方案,这两种解决方案对我来说似乎是自然而然的方法。
答案 1 :(得分:2)
最简单的方法是使用ARRAY
constructor's sub-query variant:
SELECT
person.person_name,
ARRAY(SELECT animal_name FROM pet WHERE person.person_name = pet.person_name) AS pets
FROM
person;
答案 2 :(得分:1)
您可以使用COALESCE
替换NULL
值:
SELECT
person.person_name,
array_agg(coalesce(pet.animal_name,'')) AS pets
FROM
person LEFT JOIN pet ON person.person_name = pet.person_name
GROUP BY
person.person_name
;
答案 3 :(得分:0)
我只想补充一下这是6岁
array [] :: varchar []