【问题标题】:postgres aggregate join matches to an array fieldpostgres 聚合连接匹配到数组字段
【发布时间】:2018-11-14 11:32:10
【问题描述】:

我有以下架构 + 数据:

create table org_users (
  id character varying (255),
  perdiem_ids character varying (255) --JSONized fk to perdiems.id. example data below
);

create table perdiems (
  id integer,
  name character varying(255)
);

insert into perdiems (id, name) values (1, 'perdiem 1');
insert into perdiems (id, name) values (2, 'perdiem 2');
insert into perdiems (id, name) values (3, 'perdiem 3');

insert into org_users (id, perdiem_ids) values ('user1', '{"allowed_per_diem_ids":[1, 2]}');
insert into org_users (id, perdiem_ids) values ('user2', '{"allowed_per_diem_ids":[2, 3]}');
insert into org_users (id, perdiem_ids) values ('user3', '{"allowed_per_diem_ids":[3, 1]}');

现在,我想要每个 org_user 允许的 perdiem 名称列表,例如:

org_user_id | allowed_per_diem_names
------------|---------------------------
user1       | ['perdiem 1', 'perdiem 2']
user2       | ['perdiem 2', 'perdiem 3']
user3       | ['perdiem 3', 'perdiem 1']

如果我使用以下查询,我可以获得单个用户的 perdiem 名称,但是记录是重复的,因为它是一个连接。

select ou.id, p.name from org_users ou
    left join perdiems p ON p.id = ANY (SELECT json_array_elements(perdiem_ids::JSON->'allowed_per_diem_ids')::text::int from org_users);

输出:

| id    | name      |
| ----- | --------- |
| user1 | perdiem 1 |
| user1 | perdiem 2 |
| user1 | perdiem 3 |
| user2 | perdiem 1 |
| user2 | perdiem 2 |
| user2 | perdiem 3 |
| user3 | perdiem 1 |
| user3 | perdiem 2 |
| user3 | perdiem 3 |

现在,以我期望的格式获取记录的方法是什么?我希望连接操作的输出成为数组字段的单个元素。

【问题讨论】:

    标签: sql arrays postgresql join


    【解决方案1】:

    使用array_agg

    select ou.id, array_agg(  pd.name  ORDER BY jp.id)
    from org_users ou cross join lateral
        json_array_elements_text(((ou.perdiem_ids)::json->'allowed_per_diem_ids')::json)
            with ORDINALITY as jp(perdiem,id) join
          perdiems pd
       on pd.id = jp.perdiem::int
       GROUP BY ou.id;
    

    Demo

    【讨论】:

    • 我已经接受了这个答案,因为它解决了问题,但是如果不使用 ou.id 上的 GROUP BY 子句,是否可以解决这个问题?因为,我正在 org_users 之上构建一个视图,该视图具有一些其他字段,因此也需要一些其他联接(例如 allowed_per_diem_ids,我可能在类似于 perdiems(cost_centers)的表上具有诸如 allowed_cost_center_names、allowed_floor_names 等字段、地板等)。
    • 基本上我想构建一个类似的视图:org_user_id (text), perdiem_names (text[]), cost_center_names (text[]), floor_names (text[]),其中各个 id 存储在 org_users 表中。为了简洁起见,我只是在这里提出了这样的问题。
    • @Sankar :您可以将其作为一个单独的问题提出。我相信这回答了您最初的问题。
    • 完成。将其作为一个单独的问题 stackoverflow.com/questions/53305373/… 提出,其中包含更多细节和稍微更改的架构结构,以更准确地解释问题。谢谢。
    【解决方案2】:

    我认为这会让你到达那里:

    select *
    from org_users ou cross join lateral
         json_array_elements_text(((ou.perdiem_ids)::json->'allowed_per_diem_ids')::json) ou_id join
         perdiems pd
         on pd.id = ou_id::int;
    

    Here 是一个 dbfiddle。

    【讨论】:

    • 这仍然返回重复的记录。我只希望每个 org_user 有一行。
    猜你喜欢
    • 2019-04-17
    • 2023-01-04
    • 1970-01-01
    • 1970-01-01
    • 2020-12-10
    • 2021-08-19
    • 1970-01-01
    • 2016-10-14
    • 2018-09-17
    相关资源
    最近更新 更多