Результат выборки на основе эксклюзивных значений: mysql & laravel - PullRequest
0 голосов
/ 21 сентября 2019

Из-за моего слабого словарного запаса я не уверен, что название моего вопроса правильное, но я пытаюсь объяснить свои потребности как можно подробнее.Спасибо, что прошли.

У меня есть таблица, предназначенная для хранения участников мероприятия.Диаграмма ниже.

event_id | user_id
---------|---------------------
1        | 23
1        | 32
3        | 23
3        | 32
3        | 67

Я хочу получить event_id, основываясь на предоставленных значениях user_id, но так, чтобы я показывал только тот event_id, который предоставил исключительно пользователям.

Например, основываясь на приведенной выше диаграмме таблицы, если я даю только пользовательские значения = (23, 32), мне нужно получить только событие 1, а не 1 и 3, даже если событие 3 также имеет вышеуказанных пользователей.Я пытаюсь получить события, предназначенные только для определенных пользователей.

Вот моя реализация laravel:

DB::table('events_users')->whereIn('user_id', [23, 32])
                         ->get();

Это выбирает все события, которые имеют выше пользователей, но я хочу единственное событие с идентификатором 1на основе приведенной выше диаграммы.Мое текущее решение - написать еще один слой кода после выборки, где я сопоставляю количество пользователей в каждом событии из результата запроса с требуемым количеством.Например, если я ищу эксклюзивное событие только для 2 пользователей, тогда я отфильтрую события из результата по количеству пользователей в этом событии.Извините за слабый словарный запас, но я изо всех сил пытаюсь объяснить.

Есть ли способ достичь того, что я хочу, с помощью одного запроса?

Ответы [ 3 ]

0 голосов
/ 21 сентября 2019

Я думаю, что следующее решение также в порядке:

SELECT DISTINCT event_id  FROM events_users GROUP BY event_id 
HAVING GROUP_CONCAT(DISTINCT user_id ORDER BY user_id asc SEPARATOR ',')="23,32"

Вы можете отсортировать и объединить массив user_id в строку перед запросом.

Подход построителя запросов Laravel:

$user_id_str=implode(",",[23,32]);
DB::table('events_users')
    ->selectRaw("distinct event_id")
    ->groupBy('event_id')
    ->havingRaw("GROUP_CONCAT(DISTINCT user_id ORDER BY user_id asc SEPARATOR ',')='$user_id_str'")->get();
0 голосов
/ 21 сентября 2019

РЕДАКТИРОВАТЬ: Это решение не работает для сценария, где есть несколько событий с одним и тем же видом эксклюзивных членов.Это неверное решение.Я приношу извинения. Решение от Фила работает, поэтому я пометил его как решение.

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

DB::table('events_users')
                    ->whereIn('user_id', [23, 32])
                    ->havingRaw('count(user_id) = ?', [2])
                    ->get();

Это дает мне эксклюзивные события, в которых есть только пользователи 23 и 32, но нет других участников.Я сделал предположение, что данные пользователи и количество пользователей являются взаимоисключающими, потому что в событии не будет повторяющихся записей пользователя.дайте мне знать, если это не удастся в любом сценарии.

0 голосов
/ 21 сентября 2019

Одним из подходов SQL будет использование фильтрации на основе условного агрегирования.Мы агрегируем по событию, используя GROUP BY, а затем отфильтровываем строки, используя предложение HAVING:

SELECT event_id 
FROM events_users 
GROUP BY event_id 
HAVING 
  SUM(user_id = 23) -- event exists for user = 23
  AND 
  SUM(user_id = 32) -- event exists for user = 32
  AND 
  NOT SUM(user_id NOT IN (23,32)) -- no other row exists other than user 23 and 32
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...