Найти пользователей не в организации - PullRequest
1 голос
/ 17 октября 2011

Учитывая эти данные:

users
  id    name
  ==    ====
  1     Alice
  2     Bob
  3     Carl

organizations
  id    name
  ==    ====
  1     Aaa
  2     Bbb

memberships
  id    organization_id   user_id
  ==    ===============   =======
  1     1                 1
  2     2                 1
  3     1                 2

Я хочу найти пользователей, которые не принадлежат конкретной организации X:

  • пользователей, у которых вообще нет записей о членстве

    И

  • пользователей с записями о членстве, но не для организации X.

Например, я хочу, чтобы пользователи не входили в организацию 2. Я ожидаю:

users.id
========
2
3

Попытка с этим соединением не работает:

SELECT *
FROM users left join memberships on memberships.user_id = users.id
where memberships.id is null or memberships.organization_id <> 1

Возвращает пользователей 1,2,3, поскольку 1 соответствует второму условию.

Есть ли эффективный способ сделать это?

Ответы [ 5 ]

2 голосов
/ 17 октября 2011

Ограничение вашего JOIN для организации из 2, а затем проверка на ноль - это единственный способ сделать то, что вы ищете, например:

SELECT * 
FROM   users 
       LEFT JOIN memberships 
         ON memberships.user_id = users.id 
            AND memberships.organization_id = 2 
WHERE  memberships.id IS NULL 

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

SELECT * 
FROM   users 
WHERE id NOT IN (SELECT user_id from memberships where organization_id = 2 )
0 голосов
/ 17 октября 2011

Вот еще один вариант, использующий предложение с существующим:

 select * from users
 where not exists 
    (select memberships.id from memberships 
      inner join organizations on memberships.organization_id = organizations.id 
      and memberships.user_id = users.id
      where organizations.id = 2)
0 голосов
/ 17 октября 2011
select Users.*
from users 
inner join memberships 
on Users.id = memberships.id
left join organizations 
on memberships.organization_id = organizations.id 
where memberships.id is null  AND memberships.organization_id = 2 
0 голосов
/ 17 октября 2011

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

выберите "имя" из пользователей минус выберите "имя" из пользователей u внутреннее членство в членстве m на u.id = m.user_id внутреннее объединение организации o на m.organization_id = o.id и o. "name" = 'X'

0 голосов
/ 17 октября 2011
select u.*
from users u
left join memberships m
on u.id = m.user_id
left join organizations o
on m.organization_id = o.id
where m.organization_id not in (2)

РЕДАКТИРОВАТЬ: изменено, чтобы включить всех пользователей

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