在 postgres 选择中,将列子查询作为数组返回?

Posted

技术标签:

【中文标题】在 postgres 选择中,将列子查询作为数组返回?【英文标题】:in postgres select, return a column subquery as an array? 【发布时间】:2015-10-05 20:04:38 【问题描述】:

(以前也这样做过,但是记忆会消失,就像护目镜一样)

希望从users 中选择每个用户的tag.tag_ids 作为数组返回。

选择 usr_id, 姓名, (从标签 t 中选择 t.tag_id,其中 t.usr_id = u.usr_id)作为 tag_arr 来自用户 u;

嵌入查询tag_arr 将是一个数组

【问题讨论】:

@a_horse_with_no_name - 是的。太多的语言,太多年了 - 谢谢 【参考方案1】:

使用aggregate function:

select
    usr_id, 
    name, 
    array_agg(tag_id) as tag_arr
from users
join tags using(usr_id)
group by usr_id, name

或来自子查询结果的array constructor:

select
    u.usr_id, 
    name, 
    array(
        select tag_id 
        from tags t 
        where t.usr_id = u.usr_id
        ) as tag_arr
from users u

第二个选项是一个简单的单源查询,而第一个更通用,当您需要来自相关表的多个聚合时特别方便。此外,第一个变体在较大的表上应该更快。

注意,为了获得更好的性能,两个表中的usr_id 列都应该被索引。虽然users.usr_id 通常是主键,但有时可能会忘记引用列的索引也很有用。

【讨论】:

在这两个选项中,使用array_agg() 的第一个选项的执行时间会明显更好吗?我认为这取决于所涉及的数据表的大小。在一个实际项目中,我只是将这两个查询与explain analyze 进行了比较,并分别得到了120ms10s 的执行时间。我不是数据库查询计划方面的专家,因此任何有关这两者如何以不同方式执行的见解都会有所帮助。 @broc.seib - 这取决于许多因素,例如两个表中的行数、每个用户的平均标签数、Postgres 版本、服务器和硬件配置。对于较大的表,第一个查询应该比另一个查询快。不过,您的情况差异似乎太大了。原因可能是tags(usr_id) 上缺少索引,这对于第一个查询也很有用。【参考方案2】:

使用PostgreSQL的array构造函数:

select
    usr_id,
    name,
    array(select t.tag_id from tags t where t.usr_id = u.usr_id) as tag_arr
from users u;

注意:

如果您将psycopg2 与python 一起使用,那么结果也将转换为python list! (虽然对于uuid[] 数组,如果您想在python 列表中获取ID,则需要使用array(...)::text[] 将其转换为text[] 数组)。详情请见this。

【讨论】:

以上是关于在 postgres 选择中,将列子查询作为数组返回?的主要内容,如果未能解决你的问题,请参考以下文章

如何插入选择查询的结果(如果不返回任何行则默认)作为 Postgres 函数的一部分?

如何在 Postgres 中选择一列 json 对象,以便返回的行是 json 数组?

将数据选择到 Postgres 数组中

在 Postgres JSON 数组中查询

postgres:使用子查询设置数组的值?

Node-Postgres/Knex 在 JS 中返回 CITEXT[] 作为字符串,而不是字符串数组