当多行满足要求时,如何通过连接在 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 中进行选择?的主要内容,如果未能解决你的问题,请参考以下文章
在 Greenplum(Postgres 8.4)中进行多行更新时跟踪错误记录?
如何在 ruby 中使用 ssh 隧道连接 postgres 数据库