SQL 两个 JOINS 相同 table 不同的值

SQL Two JOINS same table different values

我正在制作多个内部 join:s 以便从数据库中获取数据。 根据我选择使用的关系类型,结果会发生变化。

INNER JOIN [SERVER01].[ServiceManager].[dbo].[BaseManagedEntity] AS BMEt ON rel.TargetEntityId = BMEt.BaseManagedEntityId
INNER JOIN [SERVER01].[ServiceManager].[dbo].[RelationshipType] AS RT ON rel.RelationshipTypeId = RT.RelationshipTypeId 
    AND RT.RelationshipTypeName = 'Cireson.AssetManagement.HardwareAssetHasLocation'

INNER JOIN [SERVER01].[ServiceManager].[dbo].[BaseManagedEntity] AS BMEt ON rel.TargetEntityId = BMEt.BaseManagedEntityId
INNER JOIN [SERVER01].[ServiceManager].[dbo].[RelationshipType] AS RT ON rel.RelationshipTypeId = RT.RelationshipTypeId 
    AND RT.RelationshipTypeName = 'Cireson.AssetManagement.HardwareAssetHasOrganization'

我想要的上述两个 JOIN 的值都在 BMEt.Name。

我曾尝试将第二个名称的名称 BMEt 更改为 BMEt2,将 RT 更改为 RT2,并希望能做到这一点。但后来我没有得到任何数据。 (没有错误只是没有数据)

我也试过这样使用 IN:

INNER JOIN [SERVER01].[ServiceManager].[dbo].[BaseManagedEntity] AS BMEt ON rel.TargetEntityId = BMEt.BaseManagedEntityId
INNER JOIN [SERVER01].[ServiceManager].[dbo].[RelationshipType] AS RT ON rel.RelationshipTypeId = RT.RelationshipTypeId 
    AND RT.RelationshipTypeName IN ('Cireson.AssetManagement.HardwareAssetHasOrganization','Cireson.AssetManagement.HardwareAssetHasLocation')

然后我得到了两个值,但显然在同一列中。是否可以将其分成两列,或者我应该如何检索数据?

完整查询

DECLARE @OSBuild AS VARCHAR(100)='10.0.19042'

SELECT VRS.[ResourceID] AS 'ResourceID'
       ,VRS.[Name0] AS 'Computername'
       ,VRS.[Resource_Domain_OR_Workgr0] AS 'Domain'
       ,BIOS.SerialNumber0 AS 'Serialnumber'
       ,BMEt.Name AS 'Location'
FROM [SERVER02].[dbo].[v_R_System] as VRS
INNER JOIN [SERVER02].[dbo].[v_GS_OPERATING_SYSTEM] AS vGSOS on vGSOS.[ResourceID] = VRS.[ResourceID] 
INNER JOIN [SERVER02].[dbo].v_GS_PC_BIOS AS BIOS ON BIOS.[ResourceID] = VRS.[ResourceID]
INNER JOIN [SERVER01].[ServiceManager].[dbo].[MT_Cireson$AssetManagement$HardwareAsset] AS HWA ON BIOS.SerialNumber0 = HWA.SerialNumber_C8CF2E89_7A83_1C26_0AD0_887DF9140D5A COLLATE SQL_Latin1_General_CP1_CI_AS
INNER JOIN [SERVER01].[ServiceManager].[dbo].relationship AS rel ON rel.SourceEntityId = HWA.BaseManagedEntityId

INNER JOIN [SERVER01].[ServiceManager].[dbo].[BaseManagedEntity] AS BMEt ON rel.TargetEntityId = BMEt.BaseManagedEntityId
INNER JOIN [SERVER01].[ServiceManager].[dbo].[RelationshipType] AS RT ON rel.RelationshipTypeId = RT.RelationshipTypeId 
    AND RT.RelationshipTypeName IN ('Cireson.AssetManagement.HardwareAssetHasOrganization','Cireson.AssetManagement.HardwareAssetHasLocation')
    
    WHERE VRS.Operating_System_Name_and0 NOT LIKE '%Server%' AND
        vGSOS.[Version0] = @OSBuild 
            ORDER BY BIOS.SerialNumber0 ASC

第二次尝试

DECLARE @OSBuild AS VARCHAR(100)='10.0.19042';

with a as (
    SELECT
      VRS.[ResourceID] AS [ResourceID]
      , VRS.[Name0] AS [Computername]
      , VRS.[Resource_Domain_OR_Workgr0] AS [Domain]
      , BIOS.SerialNumber0 AS [Serialnumber]
      , case RT.RelationshipTypeName
          when 'Cireson.AssetManagement.HardwareAssetHasOrganization'
          then 'Organization'
          when 'Cireson.AssetManagement.HardwareAssetHasLocation'
          then 'Location'
        end as RelTypeName
      , BMEt.Name
      
    FROM [SERVER02].[dbo].[v_R_System] as VRS
      JOIN [SERVER02].[dbo].[v_GS_OPERATING_SYSTEM] AS vGSOS
        ON vGSOS.[ResourceID] = VRS.[ResourceID] 
      JOIN [SERVER02].[dbo].v_GS_PC_BIOS AS BIOS
        ON BIOS.[ResourceID] = VRS.[ResourceID]
      JOIN [SERVER01].[ServiceManager].[dbo].[MT_Cireson$AssetManagement$HardwareAsset] AS HWA
        ON BIOS.SerialNumber0 = HWA.SerialNumber_C8CF2E89_7A83_1C26_0AD0_887DF9140D5A COLLATE SQL_Latin1_General_CP1_CI_AS

      JOIN [SERVER01].[ServiceManager].[dbo].relationship AS rel
        ON rel.SourceEntityId = HWA.BaseManagedEntityId
      JOIN [SERVER01].[ServiceManager].[dbo].[RelationshipType] AS RT
        ON rel.RelationshipTypeId = RT.RelationshipTypeId 
          AND RT.RelationshipTypeName IN ('Cireson.AssetManagement.HardwareAssetHasOrganization','Cireson.AssetManagement.HardwareAssetHasLocation')
      JOIN [SERVER01].[ServiceManager].[dbo].[BaseManagedEntity] AS BMEt
        ON rel.TargetEntityId = BMEt.BaseManagedEntityId
        
    WHERE VRS.Operating_System_Name_and0 NOT LIKE '%Server%'
      AND vGSOS.[Version0] = @OSBuild
)

select *
from a
pivot (
 max(Name) for RelTypeName in (
    [Location],
    [Organization]
  )
) as q
ORDER BY [Serialnumber] ASC

给出错误:

Msg 319, Level 15, State 1, Line 3
Incorrect syntax near the keyword 'with'. If this statement is a common table expression, an xmlnamespaces clause or a change tracking context clause, the previous statement must be terminated with a semicolon.

Completion time: 2021-06-24T13:37:17.2405171+02:00

新错误

Msg 207, Level 16, State 1, Line 40
Invalid column name 'Name'.

Completion time: 2021-06-24T13:58:13.3559097+02:00

如果我没理解错的话,你想要两组连接:

INNER JOIN
[SERVER01].[ServiceManager].[dbo].[BaseManagedEntity] BMEt
ON rel.TargetEntityId = BMEt.BaseManagedEntityId INNER JOIN
[SERVER01].[ServiceManager].[dbo].[RelationshipType] RT
ON rel.RelationshipTypeId = RT.RelationshipTypeId AND
   RT.RelationshipTypeName = 'Cireson.AssetManagement.HardwareAssetHasOrganization' INNER JOIN
[SERVER01].[ServiceManager].[dbo].[BaseManagedEntity] BMEt2
ON rel2.TargetEntityId = BMEt2.BaseManagedEntityId INNER JOIN
[SERVER01].[ServiceManager].[dbo].[RelationshipType] RT2
ON rel.RelationshipTypeId = RT2.RelationshipTypeId AND
   RT2.RelationshipTypeName = 'Cireson.AssetManagement.HardwareAssetHasLocation';

请注意:通常这是使用 LEFT JOIN 而不是 INNER JOIN 完成的。没有样本数据、期望的结果和对查询逻辑的清晰解释,这很难说,但我很确定你需要这里的外部连接。

您也可以使用 pivot 将行转换为列,如果一个 RelationshipType 可能只有一个值:

with a as (
    SELECT
      VRS.[ResourceID] AS [ResourceID]
      , VRS.[Name0] AS [Computername]
      , VRS.[Resource_Domain_OR_Workgr0] AS [Domain]
      , BIOS.SerialNumber0 AS [Serialnumber]
      , case RT.RelationshipTypeName
          when 'Cireson.AssetManagement.HardwareAssetHasOrganization'
          then 'Organization'
          when 'Cireson.AssetManagement.HardwareAssetHasLocation'
          then 'Location'
        end as RelTypeName
      , BMEt.Name
      
    FROM [SERVER02].[dbo].[v_R_System] as VRS
      JOIN [SERVER02].[dbo].[v_GS_OPERATING_SYSTEM] AS vGSOS
        on vGSOS.[ResourceID] = VRS.[ResourceID] 
      JOIN [SERVER02].[dbo].v_GS_PC_BIOS AS BIOS
        ON BIOS.[ResourceID] = VRS.[ResourceID]
      JOIN [SERVER01].[ServiceManager].[dbo].[MT_Cireson$AssetManagement$HardwareAsset] AS HWA
        ON BIOS.SerialNumber0 = HWA.SerialNumber_C8CF2E89_7A83_1C26_0AD0_887DF9140D5A COLLATE SQL_Latin1_General_CP1_CI_AS

      JOIN [SERVER01].[ServiceManager].[dbo].relationship AS rel
        ON rel.SourceEntityId = HWA.BaseManagedEntityId
      JOIN [SERVER01].[ServiceManager].[dbo].[RelationshipType] AS RT
        ON rel.RelationshipTypeId = RT.RelationshipTypeId 
          AND RT.RelationshipTypeName IN ('Cireson.AssetManagement.HardwareAssetHasOrganization','Cireson.AssetManagement.HardwareAssetHasLocation')
      JOIN [SERVER01].[ServiceManager].[dbo].[BaseManagedEntity] AS BMEt
        ON rel.TargetEntityId = BMEt.BaseManagedEntityId
        
    WHERE VRS.Operating_System_Name_and0 NOT LIKE '%Server%'
      AND vGSOS.[Version0] = @OSBuild
)

select *
from a
pivot (
  max(Name) for RelTypeName in (
    [Location],
    [Organization]
  )
) as q
ORDER BY [Serialnumber] ASC

db<>fiddle 一些简化的例子 is here