获取连接的逆?

Posted

技术标签:

【中文标题】获取连接的逆?【英文标题】:Get the inverse of a join? 【发布时间】:2010-11-17 20:32:29 【问题描述】:

我使用的是 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、UserID 和所有用户信息的视图,但仅适用于非附加用户。

我不知道该怎么做,也许是 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
     )

【问题讨论】:

【参考方案1】:

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

【讨论】:

第一个查询有效,但我的困惑在于我希望视图具有用户不属于的 GroupId。如果使用 OUTER JOIN,GroupId 将为 null。【参考方案2】:

如果我理解正确,您将不得不对用户和组做一个卡特斯结果,并减少从 GroupUsers 派生的结果。

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

编辑:笛卡尔结果将为您提供用户 * 组。您必须从中减去 GroupUsers。很抱歉,我没有准备好 SQL,目前无法试用。

【讨论】:

你是对的 - 我不知道为什么我没有想到这一点。所以这个交叉连接/相关子查询似乎工作: SELECT G.GroupId, U.* FROM Groups G CROSS JOIN Users U WHERE U.UserId NOT IN (SELECT UserId FROM ou_GroupUsers WHERE GroupId=G.GroupId) 如果有人知道更好(更有效)的方法,请告诉我。谢谢 shahkalpesh。 我不确定性能,但您可以使用 NOT EXISTS。此外,如果 SQL 支持 EXCEPT - 那也应该可以。【参考方案3】:

我不知道如何通过活动记录来让以前的版本工作,在那里找到了一些方法,但必须在语句中编写 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%。

【讨论】:

以上是关于获取连接的逆?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 JGit 获取提交的文件列表

从 CoreData 关系中获取错误实体的对象

逆地理编码-离线版-part1

如何在 Laravel 中获取数据库字段类型?

创建java正则表达式以获取href链接

微信小程序+腾讯地图 获取定位与地图选点插件