如何在 jsonb 对象数组上应用过滤器 - 聚合后?
How to apply a filter on jsonb array of objects - after aggregating?
我有一个遵循 select 的声明:
SELECT
cards.*,
COUNT(cards.*) OVER() AS full_count,
p.printing_information
FROM
cards
LEFT JOIN
(SELECT
pr.card_id, jsonb_agg(to_jsonb(pr)) AS printing_information
FROM
printings pr
GROUP BY
pr.card_id) p ON cards.card_id = p.card_id
WHERE
...
我希望能够查询 printings
table 中的 set_id
。我试图在上面的 select 语句中通过包含 pr.set_id
来做到这一点,但它随后需要一个 GROUP BY pr.card_id, pr.set_id
然后每次打印一行而不是在 printing_information
中打印所有内容子数组。
除非我确定如何执行上述操作,否则是否可以在 jsonb 的 printing_information
数组中进行搜索?
理想情况下,我希望能够做类似的事情:
WHERE p.printing_information->set_id = '123'
不幸的是我不能这样做,因为它在一个数组中。
实现此目标的最佳方法是什么?我可以对结果进行 post 处理以去除不必要的结果,但我觉得一定有更好的方法。
SELECT cards.*
, count(cards.*) over() AS full_count
, p.printing_information
FROM cards
LEFT JOIN (
SELECT pr.card_id, jsonb_agg(to_jsonb(pr)) AS printing_information
FROM printings pr
WHERE pr.set_id = '123' -- HERE!
GROUP BY pr.card_id
) p ON cards.card_id = p.card_id
WHERE ...
这比事后过滤 便宜得多。并且可以通过 (set_id)
上的索引来支持 - 不同于任何在动态生成的 jsonb
列上进行过滤的尝试。
这很有效,但无论如何我们都需要聚合 table printings
中的所有或大部分行。但是您添加的 WHERE ...
意味着在外部 SELECT
上有更多过滤器。如果这导致只需要 printings
中的几行,则 LATERAL
子查询应该更有效:
SELECT cards.*
, count(cards.*) OVER() AS full_count
, p.printing_information
FROM cards c
CROSS JOIN LATERAL (
SELECT jsonb_agg(to_jsonb(pr)) AS printing_information
FROM printings pr
WHERE pr.card_id = c.card_id
AND pr.set_id = '123' -- here!
) p
WHERE ... -- selective filter here?!?
参见:
另外,这里没有“jsonb 数组”。子查询生成一个 jsonb
包含一个数组。
我有一个遵循 select 的声明:
SELECT
cards.*,
COUNT(cards.*) OVER() AS full_count,
p.printing_information
FROM
cards
LEFT JOIN
(SELECT
pr.card_id, jsonb_agg(to_jsonb(pr)) AS printing_information
FROM
printings pr
GROUP BY
pr.card_id) p ON cards.card_id = p.card_id
WHERE
...
我希望能够查询 printings
table 中的 set_id
。我试图在上面的 select 语句中通过包含 pr.set_id
来做到这一点,但它随后需要一个 GROUP BY pr.card_id, pr.set_id
然后每次打印一行而不是在 printing_information
中打印所有内容子数组。
除非我确定如何执行上述操作,否则是否可以在 jsonb 的 printing_information
数组中进行搜索?
理想情况下,我希望能够做类似的事情:
WHERE p.printing_information->set_id = '123'
不幸的是我不能这样做,因为它在一个数组中。
实现此目标的最佳方法是什么?我可以对结果进行 post 处理以去除不必要的结果,但我觉得一定有更好的方法。
SELECT cards.*
, count(cards.*) over() AS full_count
, p.printing_information
FROM cards
LEFT JOIN (
SELECT pr.card_id, jsonb_agg(to_jsonb(pr)) AS printing_information
FROM printings pr
WHERE pr.set_id = '123' -- HERE!
GROUP BY pr.card_id
) p ON cards.card_id = p.card_id
WHERE ...
这比事后过滤 便宜得多。并且可以通过 (set_id)
上的索引来支持 - 不同于任何在动态生成的 jsonb
列上进行过滤的尝试。
这很有效,但无论如何我们都需要聚合 table printings
中的所有或大部分行。但是您添加的 WHERE ...
意味着在外部 SELECT
上有更多过滤器。如果这导致只需要 printings
中的几行,则 LATERAL
子查询应该更有效:
SELECT cards.*
, count(cards.*) OVER() AS full_count
, p.printing_information
FROM cards c
CROSS JOIN LATERAL (
SELECT jsonb_agg(to_jsonb(pr)) AS printing_information
FROM printings pr
WHERE pr.card_id = c.card_id
AND pr.set_id = '123' -- here!
) p
WHERE ... -- selective filter here?!?
参见:
另外,这里没有“jsonb 数组”。子查询生成一个 jsonb
包含一个数组。