агрегатные соединения postgres соответствуют полю массива - PullRequest
0 голосов
/ 14 ноября 2018

У меня есть следующая схема + данные:

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]}');

Теперь я хочу список разрешенных имен perdiem для каждого org_user, например, что-то вроде:

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 |

Теперь, что такоеспособ получить записи в форматах, которые я ожидаю?Я хочу, чтобы выходные данные операций соединения стали отдельными элементами поля массива.

Ответы [ 2 ]

0 голосов
/ 14 ноября 2018

Использование 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;

Демо

0 голосов
/ 14 ноября 2018

Я думаю, что это поможет вам:

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;

Здесь - это дб <> скрипка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...