一对多sql select连接成一行

li9yvcax  于 2021-07-24  发布在  Java
关注(0)|答案(2)|浏览(477)

我用的是postgres,我有以下方案。
订单

| id |    status   |
|----|-------------|
|  1 |  delivered  |
|  2 | recollected |

评论

| id |   text  | user | order |
|----|---------|------|-------|
|  1 | texto 1 |  10  |   20  |
|  2 | texto 2 |  20  |   20  |

因此,在这种情况下,订单可以有许多注解。
我需要迭代顺序,得到如下结果:

| id |    status   |    comments    |
|----|-------------|----------------|
|  1 |  delivered  | text 1, text 2 |
|  2 | recollected |                |

我试着用左连接,但没用

SELECT
    Order.id,
    Order.status,
    "Comment".text
FROM  "Order" 
LEFT JOIN "Comment" ON Order.id = "Comment"."order"

它返回:

| id |    status   | text   |
|----|-------------|--------|
|  1 |  delivered  | text 1 |
|  1 |  delivered  | text 2 |
|  2 |  recollected|        |
f87krz0w

f87krz0w1#

你就快到了-你只需要:

SELECT
    o.id,
    o.status,
    STRING_AGG(c.text, ',') comments
FROM  "Order" o
LEFT JOIN "Comment" c ON p.id = c."order"
GROUP BY o.id, o.status

我强烈建议不要使用名为 order :因为它与语言关键字冲突。我还建议尽可能避免引用标识符,因为它们会使查询的编写时间更长,没有任何好处。
请注意,还可以使用相关子查询:

SELECT
    o.id,
    o.status,
    (SELECT STRING_AGG(c.text, ',') FROM "Comment" c WHERE c."order" = p.id) comments
FROM  "Order" o
pxyaymoc

pxyaymoc2#

你可以和我一起工作 LEFT JOIN 并在连接后聚合。但通常先聚合然后再加入更有效。
如果 "Comment" 涉及到:

SELECT o.id, o.status, c.comments
FROM   "Order" o
LEFT   JOIN (
   SELECT "order" AS id, string_agg(text, ', ') AS comments
   FROM   "Comment"
   GROUP  BY 1
   )  c USING (id);

索引无关紧要,但大多数行都必须读取。
对于只有一小部分行(例如,如果在 "Order" ):

SELECT o.id, o.status, c.comments
FROM   "Order" o
LEFT   JOIN LATERAL (
   SELECT string_agg(text, ', ')  AS comments
   FROM   "Comment"
   WHERE  "order" = o.id
   )  c ON true
WHERE  <some_selective_filter>;

在这种情况下,请确保在 ("Comment"."order") ,或更专业的,包括 text :

CREATE INDEX foo ON "Comment" ("order") INCLUDE (text);

相关:
将一列的多个结果行串联成一行,并按另一列分组
一个查询中有多个array\u agg()调用
具有主键和外键的查询是否比仅具有主键的查询运行得更快?
旁白:在postgres中考虑合法的,小写的,无引号的标识符。特别是,不要(ab-)使用完全保留的sql关键字,比如 ORDER 作为标识符。更清楚,更少的潜在的偷偷摸摸的错误。请参见:
postgresql列名是否区分大小写?

相关问题