Проблема
У меня есть три модели, значительно упрощенные для целей этого вопроса:
User:
- id
Event:
- id
- user_id (FK)
Stream:
- id
- event_id (FK)
- user_id (FK)
Я использую PostgresQL
Допустим, у меня есть два пользователя с идентификаторами: 1, 2.
Я хочу получить все События, у которых есть хотя бы один Поток, по Пользователю 1. Я также хочу исключить любые События, у которых есть хотя бы один Потокпо пользователю 2.
Набор данных
Stream: ID: 1, User: 1, Event: 1
Stream: ID: 2, User: 1, Event: 1
Stream: ID: 3, User: 1, Event: 2
Stream: ID: 4, User: 2, Event: 2
Stream: ID: 5, User: 2, Event: 3
Stream: ID: 6, User: 2, Event: 3
Для целей данного примера предположим, что это все потоки в системе.
Текущий запрос активной записи
# Keep in mind this is on the User model. So self=User 1
Event.joins(:streams)
.merge( Stream.where(user: self).where.not(user: User.find(2)) )
.....
Результирующий запрос:
SELECT events.*
FROM events
INNER JOIN streams ON streams.event_id = events.id
WHERE streams.user_id = 1 AND streams.user_id != 2
Текущий результат
Ожидаемый:
Event 1
Факт:
Event 1
Event 2
В настоящее время это соответственно возвращает только события, имеющие по крайней мере один поток пользователя 1, однако это не исключает те события, которые также имеют по крайней мере один поток пользователем 2.
Как правильно выполнить это в SQL и ненужный бонус в Active Record?