当多行满足要求时,如何通过连接在 PostgreSQL 中进行选择?

Posted

技术标签:

【中文标题】当多行满足要求时,如何通过连接在 PostgreSQL 中进行选择?【英文标题】:How to do selection in PostgreSQL with join when more than one row satisfies requirements? 【发布时间】:2017-07-05 20:31:38 【问题描述】:

当要加入的值超过 1 个时,在进行 INNER JOIN 时如何选择以在一个单元格中获取 JSON 数组?

前表:

T1:

id | name
1    Tom
2    Dom

T2:

user_id | product
1         Milk
2         Cookies
2         Banana

我当然会SELECT * FROM T1 INNER JOIN T2 ON T1.id = T2.user_id。 但后来我得到:

id | Name | product
1   Tom     Milk
2   Dom     Cookies
2   Dom     Banana

但我想得到:

id | Name | product
1   Tom     ["product":"Milk]
2   Dom     ["product":"Cookies", "product":"Banana"]

如果我使用agg 函数做某事,那么我需要将其他所有内容放在GROUP BY 中,在那里我至少有10 个参数。整个查询需要 5 分钟以上。

我的T1 大约有 4000 行,T2 大约有 300 000 行,每行都与 T1 中的某些行相关联。

有没有更好的办法?

【问题讨论】:

array_agg()? postgresql.org/docs/current/static/functions-aggregate.html 【参考方案1】:

使用LATERAL 可以解决它,如下所示:

-- The query
SELECT  *
FROM    table1 t1,
LATERAL (   SELECT  jsonb_agg(
                        jsonb_build_object( 'product', product )
                    )
            FROM    table2
            WHERE   user_id = t1.id
        ) t2( product );

-- Result
 id | name |                     product
----+------+-------------------------------------------------
  1 | Tom  | ["product": "Milk"]
  2 | Dom  | ["product": "Cookies", "product": "Banana"]
(2 rows)


-- Test data
CREATE TABLE IF NOT EXISTS table1 (
    id      int,
    "name"  text
);

INSERT INTO table1
VALUES  ( 1, 'Tom' ),
        ( 2, 'Dom' );

CREATE TABLE IF NOT EXISTS table2 (
    user_id     int,
    product     text
);

INSERT INTO table2
VALUES  ( 1, 'Milk' ),
        ( 2, 'Cookies' ),
        ( 2, 'Banana' );

【讨论】:

以上是关于当多行满足要求时,如何通过连接在 PostgreSQL 中进行选择?的主要内容,如果未能解决你的问题,请参考以下文章

选择多行时Postgres慢

EasyUI datagrid 如何默认选择多行

在 Greenplum(Postgres 8.4)中进行多行更新时跟踪错误记录?

如何在 ruby​​ 中使用 ssh 隧道连接 postgres 数据库

如何使用 node-postgres 将多行正确插入 PG?

Ruby On Rails Heroku Postgres数据库SSL连接