【问题标题】:Postgres join with array type resulting in array columnPostgres加入数组类型导致数组列
【发布时间】:2021-10-27 01:17:44
【问题描述】:

我在这里看到过类似的问题,但我找到的解决方案似乎都没有给我想要的结果。

所以我有两张桌子:

卡片表包含具有唯一 ID 和其他元数据(铸造成本等)的收藏卡片:

Cards
| id INTEGER | name TEXT | ... |

Prints 表包含 Cards 表中卡片的打印信息(这是因为同一张卡片可以通过不同的卡片组打印出不同的版本):

Prints
| id INTEGER | card_id INTEGER | set TEXT | ... |

我想做的是能够查询给定的卡片,但在单行响应中包含所述卡片的所有打印。在某种程度上,我已经能够做到这一点,但是如果一张卡片有 6 次打印,它将产生 6 行,每行包含所有打印信息,作为 JSON 格式的字符串。

我一直在尝试使用的查询如下:

SELECT DISTINCT(cards.id), cards.*, array_agg(printings.*) FROM cards
LEFT JOIN printings ON cards.id=printings.card_id
WHERE cards.name="C1" 
GROUP BY cards.id,printings.id ORDER BY cards.id;

这导致输出如下(并且打印信息只是一个字符串):

| id | name | ... |        printing_information            |
| 1  | C1   | ... | { printInfo1, printInfo2, printInfo3 } |
| 1  | C1   | ... | { printInfo1, printInfo2, printInfo3 } |
| 1  | C1   | ... | { printInfo1, printInfo2, printInfo3 } |
| 1  | C1   | ... | { printInfo1, printInfo2, printInfo3 } |
| 1  | C1   | ... | { printInfo1, printInfo2, printInfo3 } |
| 1  | C1   | ... | { printInfo1, printInfo2, printInfo3 } |

我希望能够将打印件与卡片连接起来,以便产生响应:

| id | name | ... |        printing_information            |
|  1 | C1   | ... | { print1Info, print2Info, print3Info } |
|  2 | C2   | ... | { print1Info, print2Info }             |

是否值得在一个查询中完成所有这些操作?我可以通过一些小的后期处理来实现这一点,但这是否会像需要多个查询一样高效,并且不会那么漂亮,因为它可能用于多张卡片并且搜索多个 id 似乎很混乱。

任何帮助将不胜感激!

【问题讨论】:

  • 请注意,distinct 不是一个函数。它始终适用于选择列表中的 所有 列。用括号括住其中一列不会改变任何东西并且是无用的。 distinct (a),b,cdistinct a,(b),cdistinct a,b,(c)distinct a,b,c 相同。结合group by就更没用了
  • 感谢您的解释。 Distinct 更像是晚上的最后一次尝试,看看它是否只会给我一行而不是我看到的 6 行。

标签: sql arrays postgresql join


【解决方案1】:

您需要先聚合prints 表,然后加入cards 表。

SELECT c.*, p.printing_information
FROM cards c
  LEFT JOIN (
    select pr.card_id, jsonb_agg(to_jsonb(pr))  as printing_information
    from printings pr
    group by pr.card_id 
  ) p ON c.id = p.card_id
WHERE c.name = 'C1'
ORDER BY c.id;

to_jsonb(pr)printings 表中的整行转换为 JSON 值。然后使用jsonb_agg() 将其聚合到一个 JSON 数组中,用于卡片的所有打印。如果您想从 JSON 中删除一些列,例如JSON 中的 card_id 和 'id' 列,您可以使用 to_jsonb(pr) - 'card_id' - 'id'

【讨论】:

  • 我还没有时间尝试这个,但感谢您的回复!出于好奇,在您看来,这是一个昂贵的查询,经常用于搜索吗?此外,如果有第三张表来提供与所有印刷相关的定价信息,我觉得扇出可能会变得昂贵。目前这只是一个有趣的项目,但拥有高性能代码库是乐趣的一部分:)
猜你喜欢
  • 1970-01-01
  • 2020-06-23
  • 1970-01-01
  • 2014-03-23
  • 2017-02-27
  • 2021-06-27
  • 2021-11-11
  • 1970-01-01
  • 2014-04-18
相关资源
最近更新 更多