Получить обратное соединение? - PullRequest
18 голосов
/ 08 августа 2009

Я использую SQL Server 2005. У меня есть три таблицы - Пользователи, Группы и GroupUsers. GroupUsers содержит два PK для отношения «многие ко многим».

Я могу получить всю информацию о пользователях для группы следующим образом:

SELECT * FROM GroupUsers JOIN Users ON GroupUsers.UserID = Users.UserId

Я хочу создать инверсию этого представления - я хочу получить список всех пользователей, НЕ прикрепленных к определенной группе. Следующий запрос выполнит это:

SELECT * FROM Users WHERE UserID NOT IN 
    (SELECT UserID FROM GroupUsers WHERE GroupID=@GroupID)

Однако я не хочу указывать группу, я хочу знать, как превратить это в представление, которое объединяет GroupID, а затем UsersID и всю информацию о пользователе, но только для неприкрепленных пользователей.

Я не уверен, как это сделать, может быть, что-то с оператором EXCEPT?

UPDATE:

Я думаю, что это мое решение, если кто-то не придумает что-то лучше:

SELECT 
   G.GroupId,
   U.*
FROM
   Groups G
CROSS JOIN
   Users U
WHERE
   U.UserId NOT IN 
     (
        SELECT 
           UserId
        FROM
           GroupUsers
        WHERE
           GroupId=G.GroupId
     )

Ответы [ 3 ]

29 голосов
/ 08 августа 2009

Вы можете использовать left outer join, чтобы захватить всех пользователей, а затем сдуть любого пользователя, к которому присоединена группа. Следующий запрос даст вам только список пользователей, для которых нет группы:

select
    u.*
from
    users u
    left outer join groupusers g on
        u.userid = g.userid
where
    g.userid is null

Если вы хотите найти всех пользователей, не входящих в конкретную группу:

select
    u.*
from
    users u
    left outer join groupusers g on
        u.userid = g.userid
        and g.groupid = @GroupID
where
    g.userid is null

Это только исключает пользователей из этой конкретной группы. Любой другой пользователь будет возвращен. Это связано с тем, что условие groupid было выполнено в предложении join, которое ограничивает строки, к которым присоединяются, а не возвращаются, что и делает предложение where.

2 голосов
/ 16 сентября 2010

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

SELECT * FROM Users WHERE UserID NOT IN 
(SELECT U.UserID FROM GroupUsers AS G, Users as U WHERE G.UserID <> U.UserID)

Не удалось проверить, однако этот запрос в рельсах работал нормально:

# Gets Pre-Clients.  Has client information but no project attached
Contact.joins(:client).includes(:projects => :primary_contact).
where("contacts.id NOT IN (select contacts.id from contacts, 
projects where projects.primary_contact_id = contacts.id)")

Спасибо за пост, я получил 90% пути туда.

2 голосов
/ 08 августа 2009

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

Это даст вам записи о пользователях, к которым не присоединены никакие группы.
Я прошу прощения, если я не правильно понял вопрос.

РЕДАКТИРОВАТЬ: декартово результат даст вам группы пользователей *. Вам придется вычесть из него GroupUsers. Извините, у меня нет готового SQL-кода, и я не могу попробовать его на этом этапе.

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