创建视图时,postgres聚合联接匹配到多个数组字段 [英] postgres aggregate join matches to multiple array fields while creating views

查看:128
本文介绍了创建视图时,postgres聚合联接匹配到多个数组字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下架构+数据:

create table org_users (
  id character varying (255),
  settings_id character varying (255) -- fk: settings.id
);

create table settings (
  id character varying (255), -- primary key settings_id
  perdiem_settings character varying (255), -- jsonised fk to perdiems.id
  floor_settings character varying (255) -- jsonised fk to floors.id
);

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

create table floors (
  id integer, -- primary key
  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 floors (id, name) values (1, 'floor 1');
insert into floors (id, name) values (2, 'floor 2');
insert into floors (id, name) values (3, 'floor 3');

insert into settings (id, perdiem_settings, floor_settings) values ('setting1', '{"allowed_per_diem_ids":[1, 2]}', '{"allowed_floor_ids":[1]}');
insert into settings (id, perdiem_settings, floor_settings) values ('setting2', '{"allowed_per_diem_ids":[2, 3]}', '{"allowed_floor_ids":[1, 2]}');
insert into settings (id, perdiem_settings, floor_settings) values ('setting3', '{"allowed_per_diem_ids":[3, 1]}', '{"allowed_floor_ids":[1, 2, 3]}');

insert into org_users (id, settings_id) values ('user1', 'setting1');
insert into org_users (id, settings_id) values ('user2', 'setting2');
insert into org_users (id, settings_id) values ('user3', 'setting3');

现在,我想创建一个视图,该视图将每个其他表的聚合汇总到自己的数组字段中.为了举例说明,我想要的视图应该像这样:

Now I want to create a view which will have aggregates from each of the other table, into an array field of its own. To explain with an example, the view that I want should be like:

org_user_id | settings_id | perdiems                   | floors
--------------------------------------------------------------------------------------------
user1       | setting1    | ['perdiem 1', 'perdiem 2'] | ['floor 1']
user2       | setting2    | ['perdiem 2', 'perdiem 3'] | ['floor 1', 'floor 2']
user3       | setting3    | ['perdiem 3', 'perdiem 1'] | ['floor 1', 'floor 2', 'floor 3']

这个问题与 postgres聚合联接匹配到数组有关字段,该字段用于处理联接匹配之外的数组字段.但是,这里我想在单个视图中创建多个数组字段,因此使用GROUP BY子句在iiuc中将不可行.

This question is somewhat related to postgres aggregate join matches to an array field which deals with creating array fields out of join matches. However, here I want to create multiple array fields in a single view and so using a GROUP BY clause will not be feasible iiuc.

我尝试过的查询是:

CREATE OR REPLACE VIEW users_settings_view AS
 SELECT ou.id AS org_user_id, <other fields...>
    FROM org_users ou
     LEFT JOIN settings pdr_s ON pdr_s.id = ou.settings_id
     LEFT JOIN perdiems pdr ON pdr.id = ANY (SELECT json_array_elements(perdiem_settings::JSON->'allowed_per_diem_ids')::text::int FROM settings)

由于连接而不为数组创建每个匹配的永久对象的重复记录.即使我像另一个stackoverflow问题中提到的那样创建了一个数组,但是如果我有多个字符串数组作为不同列的视图的一部分,它也将不起作用.我可以在单个视图中以多种方式将多个联接匹配到多个数组字段吗?

which creates duplicate records for each of the matching perdiem because of the join and not creating an array. Even if I crate an array as mentioned in the other stackoverflow question, it won't work if I have multiple string arrays as part of the view for different columns. Any way I can get multiple join matches to multiple array fields in a single view ?

推荐答案

这将为您提供结果.

select ou.id, array_agg( DISTINCT pd.name  ),
              array_agg( DISTINCT f.name   )
from org_users ou join settings s on  ou.settings_id = s.id
 cross join lateral
    json_array_elements_text(((s.perdiem_settings)::json->'allowed_per_diem_ids')::json)
       as jp(perdiem) join
      perdiems pd    
   on pd.id = jp.perdiem::int
  cross join lateral
    json_array_elements_text(((s.floor_settings)::json->'allowed_floor_ids')::json)
        as js(floor) join
      floors f
   on f.id = js.floor::int
   GROUP BY ou.id;

演示

修改

对于NULL设置,您可以使用单独的UNION ALL

For cases of NULL settings, you may use a separate UNION ALL

select id , ARRAY[NULL] as perdiems ,ARRAY[NULL] as floors FROM org_users 
WHERE settings_id IS NULL 
 UNION ALL
(
   -- The above query --
 ) ORDER BY id;

Demo2

这篇关于创建视图时,postgres聚合联接匹配到多个数组字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆