Хранение массива идентификаторов и как правильно распаковать их на выборку - PullRequest
0 голосов
/ 08 июня 2018

Это может быть отчасти и вопрос дизайна (впервые для PostgreSQL).

У меня есть три таблицы - Users, Groups и User_Group.User_Group представляет собой комбинацию 1 user_id, связанного с 0..X идентификаторами групп.

Таблицы настолько просты, насколько вы думаете (на данный момент, построение этой вещи):

Пользователь : идентификатор, имя, ....

группа : идентификатор, имя, ...

группа пользователей : идентификатор пользователя,GroupID int [], ...

Итак, прямо сейчас поле GroupID в User_Group является целочисленным массивом.Например, UserID 1 имеет значение {1,2,10,19,28}.

Цель: В моем пользовательском интерфейсе мне нужно представить этот список как имена групп (т.е.: {Group1, Group2, Group10, Group19, Group28}).

Итак, поскольку я новичок в PostgreSQL, я занимаюсь исследованиями, и мне в голову приходит пара идей - unnest, ЛЮБЫЕ и замена массивов.Все проблемы с производительностью кричат ​​мне, но я могу ошибаться (это вопрос дизайна, разумно ли хранить массив?)

Мой запрос сейчас:

select 
    u.*,
    g.group_ids
from users u
left join user_group g
    on u.id = g.user_id

Часть I 'Я пытаюсь понять, как вставить:

select ug.group_id 
from (select unnest(group_ids) group_id FROM user_group) as ug
left join groups g 
    on g.id = ug.group_id

Это просто приведет (очевидно) к дополнительной строке для каждого идентификатора группы, с которым связан человек.

Какой лучший способ сделать это?

Ответы [ 2 ]

0 голосов
/ 08 июня 2018

Там у вас есть отношение «один ко многим»:

Пользователь (1) -> (*) Группы

Для этого типа отношения не требуется промежуточная таблица дляопределение ссылки.Отношение один-ко-многим используется для того, чтобы иметь внешний ключ в дочерней таблице (в данном случае это Группы).

Результатом будет:

  • Пользователь: id, имя
  • Группа: id, name, user_id
  • И вы можете добавить ограничение в базу данных как: ALTER TABLE user ADD CONSTRAINT fk_user FOREIGN KEY (user_id) REFERENCES group;
0 голосов
/ 08 июня 2018

(Лично у меня будет столбец в таблице Users в виде Groups (int array), но ваш выбор тоже подойдет).

Это выглядело бы так (я использовал имена таблиц и полей на макушке головы, слегка измененные по сравнению с вашими):

select u.*, g.Name as GroupName
from users u
left join usergroups ug on ug.UserId = u.UserId
left join groups g on g.groupId = ANY( ug.groups );

Обновление: возможно, я неправильно понял вашу потребность.Может быть, вы имели в виду это:

select u.*, 
  (select string_agg(g.name,',') 
   from groups g 
   inner join usergroups ug on ug.groupId = g.GroupId
   where ug.UserId = u.UserID and 
         g.groupId = ANY( ug.groups )) as Groups
from users u;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...