在 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

让我知道是否适合您。