在这种情况下不理解 json_agg

Posted

技术标签:

【中文标题】在这种情况下不理解 json_agg【英文标题】:not understand json_agg in this context 【发布时间】:2021-10-05 08:38:31 【问题描述】:

参考:Query jsonb column containing array of JSON objects

begin;
CREATE TEMP TABLE segments (segments_id serial PRIMARY KEY, payload jsonb);
INSERT INTO segments (payload)
VALUES ('["kind": "person", "limit": "1", "kind": "B", "filter_term": "fin"]');
INSERT INTO segments (payload)
VALUES ('["kind": "person", "limit": "3", "kind": "A", "filter_term": "abc"]');
INSERT INTO segments (payload)
VALUES ('["kind": "person", "limit": "2", "kind": "C", "filter_term": "def"]');
commit;

CTE 查询:

 with a  as (select jsonb_array_elements(s.payload) j from segments s)
    SELECT  json_agg(a.j) AS filtered_payload from a
    where j @> '"kind":"person"';

返回: ["kind": "person", "limit": "1", "kind": "person", "limit": "3", "kind": "person", "limit": "2"]

这个查询A:

SELECT a.filtered_payload,
         a.ct_elem_row
        , sum(ct_elem_row) OVER () AS ct_elem_total
     , count(*)         OVER () AS ct_rows
FROM   segments s
           JOIN   LATERAL (
    SELECT json_agg(j.elem) AS filtered_payload, count(*) AS ct_elem_row
    FROM   jsonb_array_elements(s.payload) j(elem)
    WHERE  j.elem @> '"kind":"person"'
        ) a ON ct_elem_row > 0
WHERE  s.payload @> '["kind":"person"]';

返回:

    在 QueryA 中,结构类似于:select ... from segments s join lateral filtered_payload....segments 是 3 行横向连接与 1 行 (filtered_pa​​yload)。 filtered_payload 根据 CTE 查询仅返回行,作为合并 JSON 数组。所以总的来说,我对 QueryA 中的json_agg 感到非常困惑。

2021-10-05 16:36 +5:30 编辑: 即使在下面的代码中,a.filtered_payload 返回 3 个 jsonb 数组,而不是 1 个 arrgregate json 数组。我不知道何时已经聚合 jsonb 数组(使用 json_agg 函数)未嵌套到服务 jsonb 数组。

 SELECT a.filtered_payload, s.*
FROM   segments s
           cross  JOIN   LATERAL (
    SELECT json_agg(j.elem) AS filtered_payload
    FROM   jsonb_array_elements(s.payload) j(elem)
    WHERE  j.elem @> '"kind":"person"') a;

【问题讨论】:

当然该查询返回三个结果;毕竟,你SELECT /* no aggregate function */ FROM segments ...。这必须在segments 的每一行中为您提供至少一个结果行。你想达到什么目的? @LaurenzAlbe 我认为最后一个查询看起来像SELECT a.* FROM segments s cross JOIN LATERAL ('["kind": "person", "limit": "1", "kind": "person", "limit": "3", "kind": "person", "limit": "2"]' ::jsonb) a; 但是这个查询有语法错误。我还是不明白。我们已经将 jsonb 聚合到一个数组中。 '[“种类”:“人”,“限制”:“1”,“种类”:“人”,“限制”:“3”,“种类”:“人”,“限制” :“2”]'。 filters_payload 怎么只返回一个对象。 【参考方案1】:

我相信LATERAL JOIN 正在发挥作用。 在您的原始查询中,您对整个表数据集使用json_agg(由'"kind":"person"' 过滤)

with a  as 
    (
        select jsonb_array_elements(s.payload) j 
        from segments s
    )
SELECT  json_agg(a.j) AS filtered_payload 
from a
where j @> '"kind":"person"';

同时,在第二种情况下,您一次使用LATERAL 玩一排。这就是为什么您最终会得到 3 行具有单个 "kind":"person" 值的行,而不是具有 3 个值的唯一行。

不确定您要达到的目标,但以下内容可能会让您朝着正确的方向前进

SELECT a.filtered_payload,
    a.ct_elem_row, 
    sum(ct_elem_row) OVER () AS ct_elem_total, 
    count(*)         OVER () AS ct_rows
FROM segments s
 JOIN LATERAL (
    SELECT json_agg(j.elem) AS filtered_payload, 
        count(*) AS ct_elem_row
    FROM   segments d, lateral jsonb_array_elements(d.payload) j(elem)
    WHERE  j.elem @> '"kind":"person"'
    ) a ON ct_elem_row > 0
WHERE  s.payload @> '["kind":"person"]';

结果

                                            filtered_payload                                            | ct_elem_row | ct_elem_total | ct_rows
--------------------------------------------------------------------------------------------------------+-------------+---------------+---------
 ["kind": "person", "limit": "1", "kind": "person", "limit": "3", "kind": "person", "limit": "2"] |           3 |             9 |       3
 ["kind": "person", "limit": "1", "kind": "person", "limit": "3", "kind": "person", "limit": "2"] |           3 |             9 |       3
 ["kind": "person", "limit": "1", "kind": "person", "limit": "3", "kind": "person", "limit": "2"] |           3 |             9 |       3
(3 rows)

【讨论】:

以上是关于在这种情况下不理解 json_agg的主要内容,如果未能解决你的问题,请参考以下文章

为啥 selectAnnotation 在这种情况下不起作用?

为啥使用?在这种情况下不工作? (迅速)

为啥 DISTINCT 在这种情况下不起作用? (SQL)

为啥我的 JRadioButton 在这种情况下不起作用?

Javascript 音频播放在这种情况下不起作用

为啥这个 if 语句在这种情况下不起作用? [关闭]