use*_*521 5 postgresql join array postgresql-9.4
我正在尝试LEFT JOIN使用数组unnest()函数实现类似的功能。如果数组为空,我希望查询返回具有空值的行。因此,通过使用CASE构造,如果源数组为空,我想传递具有单个空元素的假数组,但它无法按预期工作:
查询 1
select element
from (
select array['a']::text[] as arr --< single non-null element
) sub, unnest(
(
case when array_length(sub.arr, 1) <= 0 then (array[null])::text[]
else sub.arr
end
)
) element
-- returns 1 row with element = "a"
Run Code Online (Sandbox Code Playgroud)
查询 2
select element
from (
select array[]::text[] as arr --< empty array
) sub, unnest(
(
case when array_length(sub.arr, 1) <= 0 then (array[null])::text[]
else sub.arr
end
)
) element
-- returns 0 rows (should return 1 row with element = NULL?)
Run Code Online (Sandbox Code Playgroud)
查询 3
select element
from (
select array[null]::text[] as arr --< single null element
) sub, unnest(
(
case when array_length(sub.arr, 1) <= 0 then (array[null])::text[]
else sub.arr
end
)
) element
-- return single row with element = NULL
Run Code Online (Sandbox Code Playgroud)
刚刚发现select array_length(array[]::text[], 1)返回NULL- 我的问题是为什么?
在 pgsql-hackers 上的线程“Should array_length() Return NULL”中引用Tom Lane:
问题是该语法创建了一个零维数组,而不是一个具有 1 维和零元素的数组。所以“0”是不正确的。
很难说是否array_length()应该返回NULL或0为空数组维度......
仅当长度为 时,您才能反转逻辑并处理原始源数组>= 1:
WITH tbl(id, arr) AS (
VALUES
(1, '{a}'::text[])
, (2, '{NULL}'::text[])
, (3, '{}'::text[])
, (4, '{x,y,z}'::text[])
)
SELECT id, elem
FROM tbl t
, unnest (
CASE WHEN array_length(t.arr, 1) >= 1
THEN t.arr
ELSE '{null}'::text[] END
) elem;
Run Code Online (Sandbox Code Playgroud)
为每个源行返回至少一行。
或者,更简单的是,使用实际的LEFT JOIN(FROM子句中的逗号是 的简写CROSS JOIN):
SELECT id, elem
FROM tbl t
LEFT JOIN LATERAL unnest(t.arr) elem ON true;
Run Code Online (Sandbox Code Playgroud)
如果未找到匹配项,则会自动为右表的列填充 NULL 值。正是您想要实现的目标。
有关的:
db<>在这里摆弄
| 归档时间: |
|
| 查看次数: |
12489 次 |
| 最近记录: |