我有以下SQL
查询
UPDATE container SET member_containers = members
FROM
(
SELECT inter_container_membership.owning_container_id AS owner_cont
,array_to_string(array_agg(inter_container_membership.member_container_id),',') AS members
FROM inter_container_membership
GROUP BY inter_container_membership.owning_container_id) v
WHERE container.id = owner_cont;
问题是,如果sub-query
没有返回任何内容,那么member_containers
将不会更新,我需要设置为null,如果是这种情况,我已尝试使用EXISTS
条款,但它没有用。
UPDATE container SET member_containers =
CASE WHEN EXISTS (
SELECT * FROM inter_container_membership
WHERE container.id = inter_container_membership.owning_container_id
) THEN members
ELSE NULL END
FROM (
SELECT inter_container_membership.owning_container_id AS owner_cont
,array_to_string(array_agg(inter_container_membership.member_container_id),',') AS members
FROM inter_container_membership
GROUP BY inter_container_membership.owning_container_id) v
WHERE container.id = owner_cont;
所以现在我想在更新它之前取消member_containers
,但我找不到这样做的方法。
答案 0 :(得分:2)
如果子查询没有找到任何内容,要将列设置为NULL,可以使用相关子查询而不是连接:
UPDATE container c
SET member_containers = (
SELECT string_agg(member_container_id, ',')
FROM inter_container_membership i
WHERE i.owning_container_id = c.id
GROUP BY owning_container_id
);
通常,这种查询是错误的,因为如果找不到任何内容,则不应该使列无效。但你似乎想要那样 此外,相关子查询往往是慢。考虑添加此左连接(执行相同的操作):
UPDATE container c
SET member_containers = i.members
FROM container c1
LEFT JOIN (
SELECT owning_container_id
,string_agg(member_container_id, ',') AS members
FROM inter_container_membership
GROUP BY 1
) i ON i.owning_container_id = c1.id
WHERE c.id = c1.id;
同时使用string_agg()
代替array_to_string(array_agg(...))
。需要Postgres 9.0 +。
答案 1 :(得分:0)
使用CTE:
WITH m AS (
SELECT icm.owning_container_id AS owner_cont,
array_to_string(array_agg(icm.member_container_id),',') AS members
FROM inter_container_membership icm
GROUP BY icm.owning_container_id)
UPDATE container SET member_containers = m.members
WHERE id = m.owner_cont;