【问题标题】:SQL multi level joinsSQL 多级连接
【发布时间】:2014-10-10 17:38:03
【问题描述】:

我需要加入至少 4 张桌子。表 A 是一个关联表,其中包含表 B 和 C 的 guid、Parentguid (B)、Childguid (C)。表 D 仅包含表 C 的信息。

我需要这样的结果。

B - C - D

监视器 - 计算机名称 - 活动

所以主要是显示所有的B表,只有连接到B的C表,只有与C关联的D表。

我怀疑我需要子连接 ( )。我仍然是一个新手,这在我的脑海中是有道理的,但我似乎无法使代码工作。过去 2 天我一直在玩 join。

FROM vHWDesktopMonitor mon             -- [Symantec_CMDB2].[dbo].[ResourceAssociation]
join ResourceAssociation RM on mon._ResourceGuid = RM.ParentResourceGuid 
full outer join vComputer comp on RM.ChildResourceGuid = comp.Guid 
full outer join vAsset on RM.ChildResourceGuid = vAsset._ResourceGuid 

【问题讨论】:

  • 如果您想要表 A 中的所有数据和表 A 中的表 b 中的数据,表 B 中的表 c 中的数据以及表 C 中表 D 中的数据,那么你想使用左连接。我发现blog.codinghorror.com/a-visual-explanation-of-sql-joins 对于新的 SQL 用户特别有用,因为 SQL 是基于集合的逻辑,主要是...
  • 对我来说,你必须使用 3 个内部连接 ​​mon JOIN RM JOIN comp JOIN vAsset

标签: sql sql-server-2008 join altiris


【解决方案1】:
FROM vHWDesktopMonitor A
FULL OUTER JOIN ResourceAssociation B
  on A._ResourceGuid = B.ParentResourceGuid 
LEFT JOIN vComputer C
  on B.ChildResourceGuid = C.Guid 
LEFT JOIN vAsset D
  on C.ChildResourceGuid = D._ResourceGuid 

所以上面会返回

  • 来自 A 的所有记录和来自 B 的所有记录(A、B 之间的完整外部)
  • 仅来自 C 且位于 B 中的记录(在 B 和 C 之间的左侧)
  • 仅来自 D 且位于 C 中的记录(左侧在 C 和 D 之间)

但是,如果您应用任何 where 子句限制,它可能会减少由于左连接或外连接而保留的记录...

例如,如果 A._ResourceGuid ='7' 在 A 中存在但不在 B 中; 并且您设置 where B._ResourceGuid ='7' 然后 A 记录将被保留,因为完整的外部联接将被排除(使完整的外部联接与内部联接相同)!

一个完整的外部将返回这样的数据:

A B
7 7
2
  3

如果你添加一个 where 子句 where B=7 那么你可能期望得到因为完整的外部,因为你说从两者返回所有记录...... 甲乙 7 7 2

但你最终会得到

A B
7 7

因为 where 子句出现在完整的外部之后,因此减少了 A.2 记录。 为了弥补这一点,您要么必须在完整的外部执行之前对连接进行限制,要么在 where 子句中处理它(但这种方法非常混乱,容易出现错误和性能问题)

因此,当使用外连接时,您必须将限制条件放在 JOIN 本身上,如下所示。

FROM vHWDesktopMonitor A
FULL OUTER JOIN ResourceAssociation B
  on A._ResourceGuid = B.ParentResourceGuid 
 and B._resourceGuid = '7'
LEFT JOIN vComputer C
  on B.ChildResourceGuid = C.Guid 
LEFT JOIN vAsset D
  on C.ChildResourceGuid = D._ResourceGuid 

您也可以将它放在 where 子句中,但您必须记住要考虑到表上的所有外连接,并为另一个包含空值(这只是混乱和缓慢)

FROM vHWDesktopMonitor A
FULL OUTER JOIN ResourceAssociation B
  on A._ResourceGuid = B.ParentResourceGuid 
LEFT JOIN vComputer C
  on B.ChildResourceGuid = C.Guid 
LEFT JOIN vAsset D
  on C.ChildResourceGuid = D._ResourceGuid 
WHERE (A._ResourceGuid is null OR B.ParentResourceGuid ='7')

【讨论】:

    【解决方案2】:

    如果我对你的理解正确的话,其中任何一个都应该有效”

    FROM vHWDesktopMonitor mon             -- [Symantec_CMDB2].[dbo].[ResourceAssociation]
    left join ResourceAssociation RM on mon._ResourceGuid = RM.ParentResourceGuid 
    left join vComputer comp on RM.ChildResourceGuid = comp.Guid 
    left join vAsset on comp.Guid  = vAsset._ResourceGuid 
    

    FROM vHWDesktopMonitor mon             -- [Symantec_CMDB2].[dbo].[ResourceAssociation]
    left join ResourceAssociation RM on mon._ResourceGuid = RM.ParentResourceGuid 
    left join (select [list fields here] from vComputer comp 
    join vAsset on comp.Guid  = vAsset._ResourceGuid) comp2
    on RM.ChildResourceGuid = comp2.Guid  
    

    这应该会为您提供来自 vHWDesktopMonitor 的所有记录和来自 ResourceAssociation 的相关记录,其中 vHWDesktopMonitor 中的任何记录都为空,但 ResourceAssociation 中的任何记录都没有。然后,您会在 vComputer 中获得所有记录,这些记录也在 ResourceAssociation 中。最后,您会在 vAsset 中获得 vComputer 中的所有记录。当您在第一个表中获取所有记录时,作为 alawys,如果您没有关联的记录,则其他表中的 inteh 文件将是空值。

    如果这不起作用,也许您需要向我们展示一些示例数据和预期结果。

    【讨论】:

    • 这看起来很有希望。我只是用适当的字段尝试了上述方法。出错了,但我会对其进行调整并以有效的方式回复。
    • 进展不顺利。我会坚持几天。最终结果应该是。监控 SN/计算机名称/计算机资产状态。但我得到 Monitor SN / NULL
    • 那是因为您的监控记录在一个或多个其他表中没有对应记录。这是正常的左连接行为。
    猜你喜欢
    • 1970-01-01
    • 2014-11-19
    • 1970-01-01
    • 2016-08-28
    • 2022-11-17
    • 1970-01-01
    • 2015-04-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多