【发布时间】:2010-07-01 18:04:25
【问题描述】:
(要快速回顾一下,请参阅标题为数据的部分。只能在图 A 和图 B 中得到结果,我想要的是期望的结果,尝试了答案部分中发布的所有内容。)
所有,我一直在努力在我的应用程序中巧妙地使用联接。男孩,我花了一段时间,但我想我已经掌握了这个窍门,但我无法让这个查询工作。
请帮帮我!以下是原样加入:
SELECT TOP (100) PERCENT a.Id, a.DateCreated, a.DateModified, a.LastUpdatedBy, a.AccomplishmentTypeId, a.Title, a.Description, a.ApplicableDate,
a.LocalId, at.Name AS AccomplishmentTypeName, a.Name AS AreaName, u.FirstName, u.LastName, ug.Name AS UserGroupName,
ugo.Name AS OtherUserGroupName
FROM dbo.Accomplishment AS a INNER JOIN
dbo.AccomplishmentType AS at ON at.Id = a.AccomplishmentTypeId INNER JOIN
dbo.AccomplishmentArea AS aal ON aal.AccomplishmentId = a.Id INNER JOIN
dbo.Area AS al ON al.Id = aal.AreaId INNER JOIN
dbo.UserAccomplishment AS ua ON ua.AccomplishmentId = a.Id INNER JOIN
dbo.[User] AS u ON u.Id = ua.UserId INNER JOIN
dbo.UserUserGroup AS uug ON uug.UserId = u.Id INNER JOIN
dbo.UserGroup AS ug ON ug.Id = uug.UserGroupId INNER JOIN
dbo.UserGroupType AS ugt ON ugt.Id = ug.UserGroupTypeId INNER JOIN
dbo.UserUserGroup AS uugo ON uugo.UserId = u.Id LEFT OUTER JOIN
dbo.UserGroup AS ugo ON ugo.Id = uugo.UserGroupId LEFT OUTER JOIN
dbo.UserGroupType AS ugto ON ugto.Id = ugo.UserGroupTypeId
WHERE (ug.LocalId = 2) AND (ugo.LocalId <> 2) AND (ugto.LocalId = 4)
ORDER BY a.DateCreated DESC, u.LastName, u.FirstName, u.Id, UserGroupName
现在这有点复杂,但我正在做的是从所有这些有成就的相关表中选择信息,其中有一个与之关联的用户,该用户的用户组 localId = 2,但是如果他们确实有,我还想返回 usertype.localid = 4 的用户所在的所有用户组。
让我举一些示例数据来说明这一点,现在我在数据库中有 3 个成就,如下所示:
-------(数据)
Accomplishment 1:
User: John
Usergroups: Group A (Of UserGroupType 2), Group B (Of UserGroupType 3),
Group C (Of UserGroupType 4), Group D (Of UsergroupType 4)
Accomplishment 2:
User: John
Usergroups: Group A (Of UserGroupType 2), Group B (Of UserGroupType 3),
Group C (Of UserGroupType 4), Group D (Of UsergroupType 4)
Accomplishment 3:
User: Sue
Usergroups: Group A (Of UserGroupType 2)
现在我上面的加入结果是 4 行:
-------(图 A):
Accomplishment 1, John, Group A, Group C
Accomplishment 1, John, Group A, Group D
Accomplishment 2, John, Group A, Group C
Accomplishment 2, John, Group A, Group D
现在这是正确的,因为用户拥有的每个 userGroup 都有一行 usergrouptype.localid 为 4,但是,我怎样才能使它也显示 Accomplishment 3?我首先从所有的连接都是内部连接开始,然后认为制作最后几个左连接会照顾它以返回用户,即使它没有用户组类型 localid 4 的用户组,但它没有。基本上我希望它返回 A 组中用户的任何成就,如果他们有任何用户组类型为 4 的用户组,也返回所有这些用户组。
有什么想法吗?如果我不清楚,请告诉我,这非常复杂,我可能解释得不够充分。
编辑:
(要快速回顾一下,请参阅标题为数据的部分。只能在图 A 和图 B 中得到结果,我想要的是期望的结果,尝试了答案部分中发布的所有内容。)
HLGEM 和 Tom H.s 的结果都是相同的,并且更接近我需要的结果,但仍然不符合要求。现在我在图 B 中得到 9 个结果。
-------(图 B):
Accomplishment 1, John, Group A, Group C
Accomplishment 1, John, Group A, Group D
Accomplishment 1, John, Group A, Null
Accomplishment 1, John, Group A, Group B (Group B is UsergroupType 3)
Accomplishment 3, Sue, Group A, Null
Accomplishment 2, John, Group A, Group C
Accomplishment 2, John, Group A, Group D
Accomplishment 2, John, Group A, Null
Accomplishment 2, John, Group A, Group B (Group B is UsergroupType 3)
因此,出于某种原因,它为 John 包含了一个空行,即使他有用户组类型为 4 的用户组,并且它包含一个用户组类型为 3 且不应显示的组 B 的行。
再次编辑:
(要快速回顾一下,请参阅标题为数据的部分。只能在图 A 和图 B 中得到结果,我想要的是期望的结果,尝试了答案部分中发布的所有内容。)
是的,我真的被这个难住了,我已经尝试了几乎所有在 where 子句中添加一些东西的组合,它要么是 4 行没有成就 3,要么是 9 行,其中用户 John 每个成就获得两行额外的行,或者6 行没有完成 3 和用户组类型 3 用户组的额外行。更令人费解的是,将ugto.localid = 4 添加到最后一行似乎对结果没有任何影响。它显示了我的用户组,它的用户组类型为 3,但我在查询中看不到任何可以的地方。
编辑 5/02/10
(要快速回顾一下,请参阅标题为数据的部分。只能在图 A 和图 B 中得到结果,我想要的是期望的结果,尝试了答案部分中发布的所有内容。)
我认为我希望我的设置是不可能的??无论如何,我想要的结果是这 5 行:
--------(期望的结果):
Accomplishment 1, John, Group A, Group C
Accomplishment 1, John, Group A, Group D
Accomplishment 2, John, Group A, Group C
Accomplishment 2, John, Group A, Group D
Accomplishment 3, Sue, Group A, Null
这是我尝试过的所有内容的列表以及它们给出的结果:(请原谅蹩脚的 SSMS 格式)
以下所有内容均基于此基本查询:
开始查询/尝试 1:
SELECT TOP (100) PERCENT a.Id, a.DateCreated, a.DateModified, a.LastUpdatedBy, a.AccomplishmentTypeId, a.Title, a.Description, a.ApplicableDate,
a.LocalId, at.Name AS AccomplishmentTypeName, al.Name AS AreaName, u.FirstName, u.LastName, ug.Name AS UserGroupName,
ugo.Name AS OtherUsergroupName
FROM dbo.Accomplishment AS a INNER JOIN
dbo.AccomplishmentType AS at ON at.Id = a.AccomplishmentTypeId INNER JOIN
dbo.AccomplishmentArea AS aal ON aal.AccomplishmentId = a.Id INNER JOIN
dbo.Area AS al ON al.Id = aal.AreaId INNER JOIN
dbo.UserAccomplishment AS ua ON ua.AccomplishmentId = a.Id INNER JOIN
dbo.[User] AS u ON u.Id = ua.UserId INNER JOIN
dbo.UserUserGroup AS uug ON uug.UserId = u.Id INNER JOIN
dbo.UserGroup AS ug ON ug.Id = uug.UserGroupId INNER JOIN
dbo.UserGroupType AS ugt ON ugt.Id = ug.UserGroupTypeId INNER JOIN
dbo.UserUserGroup AS uugo ON uugo.UserId = u.Id LEFT OUTER JOIN
dbo.UserGroup AS ugo ON ugo.Id = uugo.UserGroupId AND ugo.LocalId <> 2 LEFT OUTER JOIN
dbo.UserGroupType AS ugto ON ugto.Id = ugo.UserGroupTypeId AND ugto.LocalId = 4
WHERE (ug.LocalId = 2)
ORDER BY a.DateCreated DESC, u.LastName, u.FirstName, u.Id, UserGroupName
结果: 图B(见上图) 为什么不好: John 的 Nulls 出现了,并且类型 3 的用户组出现了。
尝试 2:
尝试 1,减去所有内联连接过滤,(仍然保留最后两个的左连接)和以下 where 语句:
WHERE (ug.LocalId = 2)
AND (ugo.LocalId <> 2 OR ugo.LocalId is null)
AND (ugto.LocalId = 4 OR ugto.LocalId is null)
结果: 图A(见上图) 为什么不好:不包括成就3
尝试 3:
与尝试 1 相同,更改从以下行开始:
dbo.[User] AS u ON u.Id = ua.UserId INNER JOIN
该行下的更改:
dbo.UserUserGroup AS uug ON uug.UserId = u.Id INNER JOIN
dbo.UserGroup AS ug ON ug.Id = uug.UserGroupId AND ug.LocalId = 2 INNER JOIN
dbo.UserGroupType AS ugt ON ugt.Id = ug.UserGroupTypeId INNER JOIN
dbo.UserUserGroup AS uugo ON uugo.UserId = u.Id LEFT OUTER JOIN
dbo.UserGroup AS ugo ON ugo.Id = uugo.UserGroupId AND ugo.LocalId <> 2 LEFT OUTER JOIN
dbo.UserGroupType AS ugto ON ugto.Id = ugo.UserGroupTypeId
WHERE (ugto.LocalId = 4)
ORDER BY a.DateCreated DESC, u.LastName, u.FirstName, u.Id, UserGroupName
(要快速回顾一下,请参阅标题为数据的部分。只能在图 A 和图 B 中得到结果,我想要的是期望的结果,尝试了答案部分中发布的所有内容。)
【问题讨论】:
-
我在这里看到的最大问题是 SQL 格式不佳。我几乎可以保证,如果你把它格式化得更好,你会更容易让它正常工作。
-
不知道你的意思,我的意思不是我如何输入它,但是SQL管理工作室在我执行SQL时将它转换为这种格式,但我这样阅读它也没有问题。你会如何格式化它?
-
我从不喜欢 SSMS 自己格式化 SQL 的方式。将 JOIN 关键字放在行尾对我来说毫无意义。它们不适用于所在行的条件。
标签: sql left-join inner-join join