(如需快速回顾,请参阅标题为DATA的章节。只能在图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个成就,如下所示:
-------(DATA)
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)
现在我的上面的Join结果有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
现在这是正确的,因为用户拥有的usergrouptype.localid为4的每个userGroup都有一行,但是,如何才能使它显示为完成3?我首先开始使用所有连接作为内部连接,然后考虑使用最后几个左连接将使用它来返回用户,即使它没有usergrouptype localid 4的用户组,但它没有。基本上我希望它返回组A中用户的任何成就,如果他们有任何usergrouptype 4的用户组,也返回所有这些用户组。
有什么想法?如果我不清楚请告诉我,这是非常复杂的,我可能没有足够的解释。
修改
(如需快速回顾,请参阅标题为DATA的章节。只能在图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的空行,即使他的用户组是usergrouptype 4,并且它包含一个B组的行,该行是usergrouptype 3并且不应该出现。
再次编辑:
(如需快速回顾,请参阅标题为DATA的章节。只能在图A和图B中得到结果,我想要的是期望的结果,尝试在答案部分发布的所有内容。)
是的,我对此感到非常难过,我已经尝试了将一些东西放在where子句中的所有组合,它或者是没有成就3的4行,或者是9行,其中用户John每个成就获得两个额外的行,或者6行没有完成3和另一行用户组类型3用户组。更令人费解的是,将ugto.localid = 4
添加到最后一行似乎对结果没有任何影响。它显示了我的用户组,其用户组类型为3,我在查询中没有看到任何可以的地方。
编辑5/02/10
(如需快速回顾,请参阅标题为DATA的章节。只能在图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
(如需快速回顾,请参阅标题为DATA的章节。只能在图A和图B中得到结果,我想要的是期望的结果,尝试在答案部分发布的所有内容。)
答案 0 :(得分:3)
@ ChaosPandion关于重新格式化的评论是一个好主意,但也许你需要一些帮助来理解什么是好格式。嗯,这对每个人来说可能都不一样:-)但如果我在编写你的查询,我会将其格式化如下:
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
我认为这种格式化更容易阅读。
分享并享受。
答案 1 :(得分:1)
我不确定我是否完全理解你要做的事情,但我认为你需要将你的标准移到LEFT OUTER JOIN中。如果将它放在WHERE子句中,那么如果LEFT OUTER JOIN找不到匹配项,那么这些列将显示为NULL,因此它们将无法通过WHERE子句检查。您实际上将LEFT OUTER JOIN转换为INNER JOIN。
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 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
答案 2 :(得分:1)
在学习左连接时你犯了一个经典错误,你把条件放在where子句中将它们变成内连接
试试这个
SELECT 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 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
请参阅此链接以获取对此的解释: http://wiki.lessthandot.com/index.php/WHERE_conditions_on_a_LEFT_JOIN
答案 3 :(得分:0)
这是我到目前为止重写的内容:
SELECT 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 a
JOIN dbo.AccomplishmentType AS at ON at.Id = a.AccomplishmentTypeId
JOIN dbo.AccomplishmentArea AS aal ON aal.AccomplishmentId = a.Id
JOIN dbo.Area AS al ON al.Id = aal.AreaId
JOIN dbo.UserAccomplishment AS ua ON ua.AccomplishmentId = a.Id
JOIN dbo.[User] AS u ON u.Id = ua.UserId
JOIN dbo.UserUserGroup AS uug ON uug.UserId = u.Id
JOIN dbo.UserGroupType AS ugt ON ugt.Id = ug.UserGroupTypeId
JOIN dbo.UserGroup AS ug ON ug.Id = uug.UserGroupId
JOIN dbo.UserGroupType AS ugto ON ugto.Id = ug.UserGroupTypeId
ORDER BY a.DateCreated DESC, u.LastName, u.FirstName, u.Id, UserGroupName
您有UserUserGroup
的冗余加入,并且可以合并到UserGroup
的加入,因为LEFT JOIN条件会取消之前加入到同一个表中的内容。
答案 4 :(得分:0)
你加入的都很好。这是过滤!
如果您编写的过滤器在左连接表中不允许空值,那么您的过滤器将删除左连接允许的其他记录。
LEFT JOIN 达到了ugo和ugtoWHERE (ug.LocalId = 2)
AND (ugo.LocalId <> 2 OR ugo.LocalId is null)
AND (ugto.LocalId = 4 OR ugto.LocalId is null)
PS - 混合JOIN和FILTERING标准(在ON中或两者都在WHERE中)是一种精神错乱的方法。保持理智!
编辑:在联接中发现错误:
INNER JOIN dbo.UserUserGroup AS uugo ON uugo.UserId = u.Id
应该是
LEFT JOIN dbo.UserUserGroup AS uugo ON uugo.UserId = u.Id