Postgres запрос, чтобы найти, если комбинация уже существует в соединительной таблице - PullRequest
0 голосов
/ 05 марта 2020

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

  • Учитывая приведенную ниже схему - возможно ли создать запрос, который проверит, соответствует ли комната заданным пользователи уже существуют?

  • Если эта проверка может привести к проблемам с производительностью - можете ли вы предложить другой дизайн или подход?

enter image description here

Пример данных:

- chat_id: 1, users: [1, 2, 3]
- chat_id: 2, users: [2, 3]
- chat_id: 3, users: [1]
- chat_id: 4, users: [5, 6]

Желаемые запросы :

Check if chat room for users [2, 3] exists => true, id: 2
Check if chat room for users [1, 2, 3] exists => true, id: 1
Check if chat room for users [2, 6] exists => false
Check if chat room for users [1, 2, 6] exists => false

Я использую postgres 11.2

РЕДАКТИРОВАТЬ : Я также смогу получить идентификатор чата, если данная комбинация существует.

Ответы [ 3 ]

1 голос
/ 05 марта 2020

Я думаю, что это то, что вы хотите:

select ca.chat_id
from chat_account ca
group by ca.chat_id
having count(*) filter (where account_id in (2, 3)) = 2 and
       count(*) = 2;

Вы также можете использовать:

having array_agg(account_id order by account_id) = array[2, 3]
0 голосов
/ 05 марта 2020

Основываясь на других ответах, я написал собственный запрос:

SELECT chat_id FROM chat_account
WHERE chat_id IN (
    SELECT c2.chat_id
    FROM chat_account c2
    WHERE c2.account_id IN (2, 3)
)
GROUP BY chat_account.chat_id
HAVING array_agg(chat_account.account_id) = ARRAY[2, 3]
0 голосов
/ 05 марта 2020

вам нужно что-то вроде этого

with selected_users as (select * from accounts where id in (2,3)),
users_chat_rooms as (
select chat_id,
array_agg(account_id order by account_id asc) users_in_room
from chat_account
group by chat_id
)
select * from users_chat_rooms
where chat_id in (select chat_id from chat_account where account_id in (select id from selected_users))
and users_in_room = (select array_agg(id order by id asc) from selected_users)

см. Fiddle https://dbfiddle.uk/?rdbms=postgres_11&fiddle=f360a05c57a33f5c130fcfa0d55429ff

вероятно, вы будете показывать это конкретному c пользователю, так что вы может фильтровать чаты пользователя, вошедшего в систему.

select * from users_chat_rooms
where chat_id in (select chat_id from chat_account where account_id = <logged_in_user>)
and users_in_room = (select array_agg(id order by id asc) from selected_users)

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