Postgres 不返回有关 array_agg 查询的数据,如下所示

Pax*_*Pax 5 postgresql join array coalesce sqlalchemy

当特定图书馆中没有书籍数据时,就会出现问题。考虑以下工作场景。

桌子 library

--------------------------------
| id |    name     |    owner  |
--------------------------------
|  1 |     ABC     |     A     |
|  2 |     DEF     |     D     |
|  3 |     GHI     |     G     |
--------------------------------
Run Code Online (Sandbox Code Playgroud)

桌子 books

--------------------------------
| id |    title    |  library  |
--------------------------------
|  a |     xxx     |     1     |
|  b |     yyy     |     1     |
|  c |     zzz     |     2     |
--------------------------------
Run Code Online (Sandbox Code Playgroud)

现在,当我进行如下查询时:

SELECT library.name, array_agg(b.title) AS book_list FROM library, 
(SELECT title FROM books WHERE books.library = :library_no) as b 
WHERE library.id = :library_no GROUP BY library.id
Run Code Online (Sandbox Code Playgroud)

该查询为库 1 和 2 生成输出,但不为库 3 生成输出。为什么以及如何解决此问题?(在没有图书馆书籍的情况下生成一个空列表)

所需输出:

----------------------
| name |    book_list |
----------------------
|  GHI |      {}      |   # or {null}
-----------------------
Run Code Online (Sandbox Code Playgroud)

我什至试过coalesce如下:

SELECT library.name, coalesce(array_agg(b.title), ARRAY[]::VARCHAR[]) AS book_list FROM library, 
(SELECT title FROM books WHERE books.library = :library_no) as b 
WHERE library.id = :library_no GROUP BY library.id
Run Code Online (Sandbox Code Playgroud)

Postgres 版本:12

Erw*_*ter 9

ALEFT JOIN可以解决它,就像Laurenz提供的那样。

但我建议在LATERAL子查询中使用 ARRAY 构造函数:

SELECT l.name, b.book_list
FROM   library l
CROSS  JOIN LATERAL (
   SELECT ARRAY(
      SELECT title
      FROM   books
      WHERE  library = l.id
      )
   ) b(book_list)
WHERE  l.id = :library_no;
Run Code Online (Sandbox Code Playgroud)

这样,您不需要在外部查询级别聚合,也不需要在GROUP BY那里聚合。

您也不需要COALESCE,因为空结果上的 ARRAY 构造函数已经生成了一个空数组 ( {})。

对于一个小的选择,它应该更快library- 显然查询获得单个给定库的结果。

此外,您只需要:library_no像演示一样在一个地方使用变量。

关于LATERAL加入:

关于 ARRAY 构造函数:

手册中关于连接表的基本信息。


Lau*_*lbe 5

你需要一个左连接:

... FROM library
       LEFT JOIN books ON library.id = books.library
Run Code Online (Sandbox Code Playgroud)

然后你也会得到没有书的图书馆。

  • @Pax:`COALESCE` 只能在有一行开始时介入。 (4认同)