string_agg 没有记录时返回空字符串

Mic*_*ood 8 postgresql null aggregate concat

我正在尝试在格式为 PostgreSQL 查询中返回一个文本字段

'stringOne' || string_agg(field, ',') || 'stringTwo'
Run Code Online (Sandbox Code Playgroud)

对于 group 子句中的某些元素, wherefield始终为 null。我想要并期望stringOnestringTwo在这种情况下结束,但我得到NULL.

为什么会这样,我如何完成我想要做的事情?

例子

假设我有桌子

foo                 bar
+----+--------+     +----+-------+--------------+
| id | name   |     | id | fooid | baz          |
+----+--------+     +----+-------+--------------+
|  1 | FooOne |     |  1 |     1 | FooOneBazOne |
|  2 | FooTwo |     |  2 |     1 | FooTwoBazTwo |
+----+--------+     +----+-------+--------------+
Run Code Online (Sandbox Code Playgroud)

我运行查询

SELECT
  foo.name AS foo,
  'Bazzes: ' || string_agg(bar.baz, ', ') AS bazzes
FROM
  foo LEFT JOIN bar ON bar.fooid = foo.id
GROUP BY
  foo.name
Run Code Online (Sandbox Code Playgroud)

然后我想要(并期望)得到结果集

+--------+------------------------------------+
| foo    | bazzes                             |
+--------+------------------------------------+
| FooOne | Bazzes: FooOneBazOne, FooOneBazTwo |
| FooTwo | Bazzes:                            |  <== NOT NULL
+--------+------------------------------------+
Run Code Online (Sandbox Code Playgroud)

但相反,第二行是('FooTwo', NULL). 如何修改此查询以便第二行返回('FooTwo', 'Bazzes: ')

Erw*_*ter 8

使用COALESCE捕捉并替换NULL值:

SELECT f.name AS foo
     , 'Bazzes: ' || COALESCE(string_agg(b.baz, ', '), '') AS bazzes
FROM   foo f
LEFT   JOIN bar b ON b.fooid = f.id
GROUP  BY 1;
Run Code Online (Sandbox Code Playgroud)

concat()是您发现自己的另一个方便的选择,特别是连接多个值。不过,我建议使用变体concat_ws()(“带分隔符”)以避免尾随空格。

concat_ws(' ', 'Bazzes:', string_agg(b.baz, ', ')) AS bazzes
Run Code Online (Sandbox Code Playgroud)

为什么NULL

NULL如果所有源字段都是NULL(没有非空值,准确地说),则几乎所有聚合函数都返回-count()由于实际原因,这是例外。手册:

需要注意的是,除了 之外count,当没有选择任何行时,这些函数返回一个空值。特别是,sum没有行返回空值,而不是人们所期望的零,并且array_agg在没有输入行时返回空值而不是空数组。coalesce 必要时,该函数可用于将零或空数组替换为 null。

有关的: