PostgreSQL unnest 与空数组
Posted
技术标签:
【中文标题】PostgreSQL unnest 与空数组【英文标题】:PostgreSQL unnest with empty array 【发布时间】:2013-03-02 13:48:46 【问题描述】:我使用 postgreSQL 9.1。在我的数据库中有一个看起来像的表
id | ... | values
-----------------------
1 | ... | 1,2,3
2 | ... |
其中 id 是一个整数,而 values 是一个整数数组。数组可以为空。
我需要取消嵌套此列表。如果我查询
select id, ..., unnest(values)
from table
id = 1 得到三行(如预期的那样),id = 2 没有行。有没有办法得到类似的结果
id | ... | unnest
-------------------
1 | ... | 1
1 | ... | 2
1 | ... | 3
2 | ... | null
即查询还包含具有空数组的行?
【问题讨论】:
【参考方案1】:select id,
case
when int_values is null or array_length(int_values,1) is null then null
else unnest(int_values)
end as value
from the_table;
(请注意,我将列values
重命名为int_values
,因为values
是保留字,不应用作列名)。
SQLFiddle:http://sqlfiddle.com/#!1/a0bb4/1
Postgres 10 不再允许像这样使用unnest()
。
您需要使用横向连接:
select id, t.i
from the_table
cross join lateral unnest(coalesce(nullif(int_values,''),array[null::int])) as t(i);
在线示例:http://rextester.com/ALNX23313
使用左连接而不是交叉连接可以进一步简化:
select id, t.i
from the_table
left join lateral unnest(int_values) as t(i) on true;
在线示例:http://rextester.com/VBO52351
【讨论】:
【参考方案2】:这也适用于 Postgres 10:
SELECT id, UNNEST(CASE WHEN "values" <> '' THEN "values" ELSE 'null' END)
【讨论】:
【参考方案3】:在重新审视这个问题时,我突然觉得这可以更简单更快。 反转currently accepted solution by @a_horse的逻辑:
SELECT id, CASE WHEN values <> '' THEN unnest(values) END AS value
FROM tbl
对于 空数组 以及 NULL
数组,这会在 value
中返回带有 NULL
的行,因为只有一个数组其中的元素在测试values <> ''
中产生TRUE
。
适用于 any 类型的数组,因为文字“”会自动强制转换为匹配类型。
没有明确的ELSE
分支,CASE
返回NULL
,这就是我们想要的。
带有NULL
元素的数组无论如何都会返回行。但是。我在那里发现了一个异常并发布了一个与此相关的问题:
原来是我报告 pg 9.3+ 后修复的错误。
【讨论】:
【参考方案4】:select id,
unnest (
"values"
||
(array[null]::integer[])[1:(array_upper("values", 1) is null)::integer]
)
from "table"
【讨论】:
【参考方案5】:你需要使用 self LEFT JOIN
,像这样(也在SQL Fiddle):
SELECT t.id, u.u
FROM tab t
LEFT JOIN (SELECT id, unnest(vals) u FROM tab) u
USING (id);
请注意,对于更大的表,查询的性能会很差。
【讨论】:
以上是关于PostgreSQL unnest 与空数组的主要内容,如果未能解决你的问题,请参考以下文章
具有 unnest 的 PostgreSQL 查询不返回空值的结果行
PostgreSQL unnest,嵌套字段特定元素的 WHERE 子句