在 Postgres 中执行 SELECT 语句时,如何从 JSONB 字段中获取 JSON 对象列表而不是 ID 列表?
How to fetch a list of JSON objects instead of list of IDs from a JSONB field when doing a SELECT statement in Postgres?
我有两个table,用户和模拟。 users table 有一个带有自动递增 ID 字段的用户详细信息列表。 模拟 table 包含模拟的详细信息以及关联用户的列表。模拟 table 中的 user_list
列是一个 jsonb
字段,其中包含关联用户的列表 ID。
两个 table 的示例如下:
Table 姓名:用户
数据:
ID name country age
---- ------ --------- -----
1 Jason USA 21
2 William England 40
3 Jake USA 34
.
.
.
(total 100,000 rows)
Table 名称:模拟
数据:
ID simulation_name user_list datetime
---- --------------- ---------- ----------
1 sample1 [1,2] <some datetime>
2 sample2 [5,6] <some datetime>
.
.
.
我可以使用以下查询获取有关特定国家模拟的数据
SELECT * from simulations
WHERE ARRAY(SELECT JSONB_ARRAY_ELEMENTS(user_list)::bigint)
&& ARRAY(SELECT id FROM users
WHERE country = 'USA');
这给出了以下响应
ID simulation_name datetime user_list
---- --------------- ---------- ----------
1 sample1 <some datetime> [1,2]
2 sample4 <some datetime> [1,9,12]
.
.
.
然而,这并不是我所需要的。我需要 users_list
列到 return 不仅是 ID,还有一个包含每个用户详细信息的 json 对象。
这是我真正需要的回应:
ID simulation_name datetime user_list
--- ---------------- -------------- ------------
1 sample1 <some datetime> [{"id":1,"name":"Jason","country":"USA"},{"id":2,"name":"William","country":"England"}]
.
.
如何将用户 ID 替换为用户的实际详细信息作为 JSON 对象列表以获得上述响应?
(我知道如果我遵循多对多 table 结构,这会容易得多,但由于某些业务需求,我必须遵循这个)
您可以使用连接或相关子查询检索相关用户详细信息,并使用 json_agg
将相关用户详细信息聚合到 json 数组中,如下所示。
您也可以使用 s.user_list @> u.id::text::jsonb
来确定用户是否存在于列表中。
使用加入
SELECT
s.id,
s.simulation_name,
s.datetime ,
json_agg(u.*) as user_list
FROM
simulations s
INNER JOIN
users u ON s.user_list @> u.id::text::jsonb AND
u.country='USA'
GROUP BY
s.id,s.simulation_name,s.datetime;
id
simulation_name
datetime
user_list
1
sample1
some datetime
[{"id":1,"name":"Jason","country":"USA","age":21}]
使用关联查询
SELECT * FROM (
SELECT
s.id,
s.simulation_name,
s.datetime ,
(
SELECT json_agg(u.*)
FROM users u
WHERE s.user_list @> u.id::text::jsonb AND
u.country='USA'
) as user_list
FROM
simulations s
) t
WHERE t.user_list IS NOT NULL;
id
simulation_name
datetime
user_list
1
sample1
some datetime
[{"id":1,"name":"Jason","country":"USA","age":21}]
View working demo on DB Fiddle
让我知道是否适合您。
我有两个table,用户和模拟。 users table 有一个带有自动递增 ID 字段的用户详细信息列表。 模拟 table 包含模拟的详细信息以及关联用户的列表。模拟 table 中的 user_list
列是一个 jsonb
字段,其中包含关联用户的列表 ID。
两个 table 的示例如下:
Table 姓名:用户
数据:
ID name country age
---- ------ --------- -----
1 Jason USA 21
2 William England 40
3 Jake USA 34
.
.
.
(total 100,000 rows)
Table 名称:模拟
数据:
ID simulation_name user_list datetime
---- --------------- ---------- ----------
1 sample1 [1,2] <some datetime>
2 sample2 [5,6] <some datetime>
.
.
.
我可以使用以下查询获取有关特定国家模拟的数据
SELECT * from simulations
WHERE ARRAY(SELECT JSONB_ARRAY_ELEMENTS(user_list)::bigint)
&& ARRAY(SELECT id FROM users
WHERE country = 'USA');
这给出了以下响应
ID simulation_name datetime user_list
---- --------------- ---------- ----------
1 sample1 <some datetime> [1,2]
2 sample4 <some datetime> [1,9,12]
.
.
.
然而,这并不是我所需要的。我需要 users_list
列到 return 不仅是 ID,还有一个包含每个用户详细信息的 json 对象。
这是我真正需要的回应:
ID simulation_name datetime user_list
--- ---------------- -------------- ------------
1 sample1 <some datetime> [{"id":1,"name":"Jason","country":"USA"},{"id":2,"name":"William","country":"England"}]
.
.
如何将用户 ID 替换为用户的实际详细信息作为 JSON 对象列表以获得上述响应?
(我知道如果我遵循多对多 table 结构,这会容易得多,但由于某些业务需求,我必须遵循这个)
您可以使用连接或相关子查询检索相关用户详细信息,并使用 json_agg
将相关用户详细信息聚合到 json 数组中,如下所示。
您也可以使用 s.user_list @> u.id::text::jsonb
来确定用户是否存在于列表中。
使用加入
SELECT
s.id,
s.simulation_name,
s.datetime ,
json_agg(u.*) as user_list
FROM
simulations s
INNER JOIN
users u ON s.user_list @> u.id::text::jsonb AND
u.country='USA'
GROUP BY
s.id,s.simulation_name,s.datetime;
id | simulation_name | datetime | user_list |
---|---|---|---|
1 | sample1 | some datetime | [{"id":1,"name":"Jason","country":"USA","age":21}] |
使用关联查询
SELECT * FROM (
SELECT
s.id,
s.simulation_name,
s.datetime ,
(
SELECT json_agg(u.*)
FROM users u
WHERE s.user_list @> u.id::text::jsonb AND
u.country='USA'
) as user_list
FROM
simulations s
) t
WHERE t.user_list IS NOT NULL;
id | simulation_name | datetime | user_list |
---|---|---|---|
1 | sample1 | some datetime | [{"id":1,"name":"Jason","country":"USA","age":21}] |
View working demo on DB Fiddle
让我知道是否适合您。