以下查询
SELECT jsonb_build_array(jsonb_build_object('use', 'Home'),
CASE WHEN 1 = 2 THEN jsonb_build_object('use', 'Work')
END)
产生
[{"use":"Home"},null]
当我真正想要时
[{"use":"Home"}]
我该怎么做?json_strip_nulls()
对我不起作用。
通过使用这样的PostgreSQL数组:
SELECT array_to_json(array_remove(ARRAY[jsonb_build_object('use', 'Home'),
CASE WHEN 1 = 2 THEN jsonb_build_object('use', 'Work') END], null))
它确实产生:
[{"use": "Home"}]
当然:
SELECT array_to_json(array_remove(ARRAY[jsonb_build_object('use', 'Home'),
CASE WHEN 1 = 2 THEN jsonb_build_object('use', 'Work') END,
jsonb_build_object('real_use', 'NotHome')], null))
确实产生:
[{"use": "Home"},{"real_use": "NotHome"}]
create or replace function jsonb_build_array_without_nulls(variadic anyarray)
returns jsonb language sql immutable as $$
select jsonb_agg(elem)
from unnest($1) as elem
where elem is not null
$$;
select
jsonb_build_array_without_nulls(
jsonb_build_object('use', 'home'),
case when 1 = 2 then jsonb_build_object('use', 'work') end
)
jsonb_build_array_without_nulls
---------------------------------
[{"use": "home"}]
(1 row)
我假设这个查询是动态生成的。如果您控制SQL生成,也可以使用ARRAY_AGG(...) FILTER(...)
,根据您的实际查询,它可能比使用Patrick建议的所有不同的数组转换函数更方便。
SELECT (
SELECT json_agg(v) FILTER (WHERE v IS NOT NULL)
FROM (
VALUES
(jsonb_build_object('use', 'Home')),
(CASE WHEN 1 = 2 THEN jsonb_build_object('use', 'Work') END)
) t (v)
)
或者:
SELECT (
SELECT json_agg(v)
FROM (
VALUES
(jsonb_build_object('use', 'Home')),
(CASE WHEN 1 = 2 THEN jsonb_build_object('use', 'Work') END)
) t (v)
WHERE v IS NOT NULL
)
处理此问题的另一种方法如下:
SELECT jsonb_build_array(
jsonb_build_object('use', 'Home'),
CASE
WHEN 1 = 2 THEN jsonb_build_object('use', 'Work')
ELSE '"null"'
END
) - 'null'
(不幸的是,在postgres或大多数其他DB中,null
本身实际上不可能做太多事情(
在上面的例子中,'"null"'
可以被替换为几乎任何唯一的字符串,这些字符串不会被误认为是数组中的活动数据。我不会使用数字,因为- 0
实际上会尝试从数组中删除第一个项目,而不是数组中的数字。但是,如果您愿意的话,您可能可以使用'"0"'
并使用类似- '0'
的东西来移除。
对于那些不使用CASE
的人,可以使用COALESCE
将null转换为所需的字符串(唉,postgres中没有NVL
、IFNULL
或ISNULL
,但至少COALESCE
是可移植的(