PostgreSQL 创建物化视图,根据字段和 table 列将 JSON 数组中的对象汇总到特定列中
PostgreSQL create materialized view that sums objects in JSON array into specific columns based on field and table column
给出以下 table:
create table entries (
user_id integer,
locations jsonb
);
我想创建一个包含以下结构的物化视图。这些列应从零开始,并根据位置中的内容相加。
create table entries_locations_extracted (
user_id integer,
location_1_a integer,
location_1_b integer,
location_2_a integer,
location_2_b integer
);
位置将始终是一个 JSON 数组,具有以下结构。阵列中可能存在多个位置。每个用户可能存在多个条目。
insert into entries (user_id, locations) values (123, '[
{ location=1, a=1, b=2 },
{ location=2, a=3, b=1 },
{ location=2, a=10, b=20 },
{ location=1, a=2, b=3 },
]')
insert into entries (user_id, locations) values (123, '[
{ location=1, a=100, b=200 },
]')
鉴于上面的插入。物化视图应包含以下行:
| user_id | location_1_a | location_1_b | location_2_a | location_2_b |
-----------------------------------------------------------------------
| 123 | 103 | 205 | 13 | 21 |
您可以为此使用 aggregate with a filter and a lateral query to expand the array:
SELECT
user_id,
SUM((loc->>'a')::int) FILTER (WHERE loc->'location' = '1') AS location_1_a,
SUM((loc->>'b')::int) FILTER (WHERE loc->'location' = '1') AS location_1_b,
SUM((loc->>'a')::int) FILTER (WHERE loc->'location' = '2') AS location_2_a,
SUM((loc->>'b')::int) FILTER (WHERE loc->'location' = '2') AS location_2_b
FROM
entries,
jsonb_array_elements(locations) AS loc
GROUP BY
user_id;
给出以下 table:
create table entries (
user_id integer,
locations jsonb
);
我想创建一个包含以下结构的物化视图。这些列应从零开始,并根据位置中的内容相加。
create table entries_locations_extracted (
user_id integer,
location_1_a integer,
location_1_b integer,
location_2_a integer,
location_2_b integer
);
位置将始终是一个 JSON 数组,具有以下结构。阵列中可能存在多个位置。每个用户可能存在多个条目。
insert into entries (user_id, locations) values (123, '[
{ location=1, a=1, b=2 },
{ location=2, a=3, b=1 },
{ location=2, a=10, b=20 },
{ location=1, a=2, b=3 },
]')
insert into entries (user_id, locations) values (123, '[
{ location=1, a=100, b=200 },
]')
鉴于上面的插入。物化视图应包含以下行:
| user_id | location_1_a | location_1_b | location_2_a | location_2_b |
-----------------------------------------------------------------------
| 123 | 103 | 205 | 13 | 21 |
您可以为此使用 aggregate with a filter and a lateral query to expand the array:
SELECT
user_id,
SUM((loc->>'a')::int) FILTER (WHERE loc->'location' = '1') AS location_1_a,
SUM((loc->>'b')::int) FILTER (WHERE loc->'location' = '1') AS location_1_b,
SUM((loc->>'a')::int) FILTER (WHERE loc->'location' = '2') AS location_2_a,
SUM((loc->>'b')::int) FILTER (WHERE loc->'location' = '2') AS location_2_b
FROM
entries,
jsonb_array_elements(locations) AS loc
GROUP BY
user_id;