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 &lt;&gt; '' 中产生TRUE

适用于 any 类型的数组,因为文字“”会自动强制转换为匹配类型。

没有明确的ELSE 分支,CASE 返回NULL,这就是我们想要的。

带有NULL 元素的数组无论如何都会返回行。但是。我在那里发现了一个异常并发布了一个与此相关的问题:

NULL emements lost when casting result of unnest()

原来是我报告 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 的 Jooq 表示法

具有 unnest 的 PostgreSQL 查询不返回空值的结果行

将 UNNEST 与 jOOQ 一起使用

PostgreSQL unnest,嵌套字段特定元素的 WHERE 子句

Postgresql一行变多行unnest与string_to_array,多行变一行string_agg

postgresql - 不嵌套,对于每个结果