在这种情况下不理解 json_agg
not understand json_agg in this context
参考:
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"}';
Return: [{"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"}]';
return :
- 在 QueryA 中,结构如下:
select ... from segments s join lateral filtered_payload....
segments
是 3 行横向连接与一行 (filtered_payload)。 filtered_payload
return 只有根据 CTE 查询的行,作为合并 JSON 数组。所以总的来说,我对 QueryA 中的 json_agg
很困惑。
编辑于 2021-10-05 16:36 +5:30:
即使是下面的代码,a.filtered_payload
return 3 jsonb 数组,而不是一个 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;
我相信 LATERAL JOIN
正在发挥作用。
在您的原始查询中,您对整个 table 数据集使用 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)
参考:
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"}';
Return: [{"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"}]';
return :
- 在 QueryA 中,结构如下:
select ... from segments s join lateral filtered_payload....
segments
是 3 行横向连接与一行 (filtered_payload)。filtered_payload
return 只有根据 CTE 查询的行,作为合并 JSON 数组。所以总的来说,我对 QueryA 中的json_agg
很困惑。
编辑于 2021-10-05 16:36 +5:30:
即使是下面的代码,a.filtered_payload
return 3 jsonb 数组,而不是一个 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;
我相信 LATERAL JOIN
正在发挥作用。
在您的原始查询中,您对整个 table 数据集使用 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)