使用 STRING_AGG 函数时子查询返回多行

Posted

技术标签:

【中文标题】使用 STRING_AGG 函数时子查询返回多行【英文标题】:More than one row returned by a subquery when using STRING_AGG function 【发布时间】:2021-02-03 10:54:42 【问题描述】:

尝试在 PostgreSQL 11 中执行 SELECT 查询时出现错误

select (
    SELECT STRING_AGG(u.first_name::text, ', ') 
    FROM game_authors AS gat 
    LEFT JOIN users AS u ON u.id = gat.user_id 
    WHERE gat.game_id = g.id AND gat.lang = 'uk' 
    GROUP BY gat.id ORDER BY gat.id ASC
) AS authors_string 
from "games" as "g" 
where "g"."status" != 10 
order by "g"."id" desc limit 10 offset 0

authors_string 应该作为字符串值获取。它抛出了一个错误

错误:用作表达式的子查询返回多行

我猜这是因为子查询中的 GROUP BY 并且可以使用 row_to_json 函数处理,但不知道我应该将它放在表达式中的哪个位置。 ORDER BY 不适用于 GROUP BY 表达式,因为 SELECT 中存在聚合函数。

SQL 版本

x86_64-pc-linux-gnu 上的 PostgreSQL 11.8 (Ubuntu 11.8-1.pgdg18.04+1),由 gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0 编译,64 位

【问题讨论】:

【参考方案1】:

我想你只是想删除子查询中的group by 子句:

select (
    select string_agg(u.first_name::text, ', ' order by gat.id asc) 
    from game_authors as gat 
    left join users as u on u.id = gat.user_id 
    where gat.game_id = g.id and gat.lang = 'uk' 
) as authors_string 
from games as g 
where g.status <> 10 
order by g.id desc 
limit 10

【讨论】:

【参考方案2】:

使用派生表而不是标量子选择。通常,这更有效:

select a.authors_string 
from games as g 
  join (
    SELECT gat.game_id, STRING_AGG(u.first_name::text, ', ' order by gat.id)  as authors
    FROM game_authors AS gat 
      LEFT JOIN users AS u ON u.id = gat.user_id 
    WHERE AND gat.lang = 'uk' 
    GROUP BY gat.id 
  ) a ON a.game_id = g.id
where g.status <> 10 
order by g.id desc 
limit 10 offset 0

left join 似乎没用

【讨论】:

以上是关于使用 STRING_AGG 函数时子查询返回多行的主要内容,如果未能解决你的问题,请参考以下文章

数据库子查询

SQL ---子查询

SQL 数据库 子查询及示例

数据库子查询

SQL 数据库 子查询主外键

PostgreSQL合并多行数据为一行,string_agg函数