SQL Получает пользователей по одной группе, но исключает других

#mysql #sql

#mysql #sql

Вопрос:

Я пытаюсь написать запрос, который извлекает всех пользователей, которые принадлежат к группе A , но исключает пользователей, которые принадлежат группам B , C amp; D .

Пользователи однозначно идентифицируются user_id в users таблице, но могут иметь несколько записей в groups таблице.

У меня есть следующий запрос, но он не работает:

 SELECT user_id
FROM users
LEFT JOIN groups USING (user_id)
WHERE groups.name = 'A'
AND groups.name NOT IN ('B', 'C', 'D')
  

Это просто выбирает всех пользователей из группы A .

Как включить кого-либо из группы A , но исключить их, если они находятся в группах B , C amp; D ?

Комментарии:

1. Как groups.name выглядят данные в этом файле? Это список с разделителями, как A,B ?

2. Нет, это просто varchar. В этом случае либо A , B , C либо D .

Ответ №1:

Используйте агрегацию:

 SELECT user_id
FROM groups
GROUP BY user_id
HAVING SUM(g.name = 'A') > 0 AND
       SUM(g.name IN ('B', 'C', 'D')) = 0;
  

Примечание: Вам не нужно присоединяться к users . Ваш запрос выбирает только идентификатор пользователя, который находится в groups таблице. Конечно, если вам нужны дополнительные столбцы из users , вы можете присоединиться к нему (или использовать in или exists ).

Комментарии:

1. Не могли бы вы также добавить пример для объединения?

2. @Dangerman1988 . . . Это отвечает на вопрос, который вы задали. Должно быть довольно ясно, как добавить join в запрос.

Ответ №2:

использование существует

     select t1.user_id from users t1
    where exists( select 1 from groups t2 where t1.user_id=t2.user_id
                   and t2.name='A')
   and not exists( select 1 from groups t2 where t1.user_id=t2.user_id
                        and t2.name NOT IN ('B', 'C', 'D') )
  

Комментарии:

1. Это наоборот, я хочу исключить их, если они принадлежат к любому из B, C или D

Ответ №3:

Вы можете использовать EXISTS для случая имени группы A и NOT EXISTS для случая имен групп B, C, D :

 select distinct user_id
from groups g
where 
  exists (
    select 1 from groups where user_id = g.user_id and name = 'A'
  )
  and not exists (
    select 1 from groups where user_id = g.user_id and name in ('B', 'C', 'D')
  )