得到连接的倒数?

时间:2009-08-07 22:54:51

标签: sql sql-server sql-server-2005 tsql join

我使用的是SQL Server 2005.我有三个表 - Users,Groups和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和所有用户信息的视图,但仅限于非连接用户。 / p>

我不知道如何做到这一点,也许是EXCEPT运算符?

更新:

我认为这是我的解决方案,除非有人提出更好的建议:

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 个答案:

答案 0 :(得分:29)

您可以使用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子句的作用。

答案 1 :(得分:2)

如果我理解正确,你将不得不做一个用户的卡特尔结果&分组并减少从GroupUsers派生的结果。

这将为您提供没有附加任何组的用户的记录 如果我没有正确理解这个问题,我会道歉。

编辑:笛卡尔结果将为您提供用户*组。您将不得不从中减去GroupUsers。对不起,我没有SQL准备好它&在这一点上无法尝试。

答案 2 :(得分:2)

我无法弄清楚如何通过活动记录使以前的版本工作,得到了一些方法,但必须在语句中编写SQL。我相信这也可以完成同样的事情。

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

无法测试但是在rails中的这个查询工作得很好:

# 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%的路程。