检查连接表中是否存在记录

时间:2015-12-18 19:50:25

标签: sql sql-server

我有一个设备实体,根据是否已售出,可能有也可能没有拥有者:

DEVICE
======
Id
OwnerId (null)
DeviceTypeId (not null)

Owner
=====
Id
Name

每种类型的设备都可以具有不同的功能,而每种功能都可以映射到多种类型,因此我有一个联结表。

DeviceType
====
Id
ModelNum

Capability
==========
Id
CapabilityName

Type_Capability
===============
Id
DeviceTypeId
CapabilityId

我想写一个查询,如果它存在,将返回设备的所有者,以及设备是否具有名称" overclock"的能力。

我有以下内容:

SELECT device.Id, owner.Name, ??? as [hasOverclock]
FROM Device device
LEFT OUTER JOIN Owner owner on owner.Id = device.ownerId
INNER JOIN DeviceType deviceType on deviceType.Id = device.DeviceTypeId
INNER JOIN TypeCapability typeCapability on typeCapability.DeviceTypeId = deviceType.Id
INNER JOIN Capability capability on capability.Id = typeCapability.CapabilityId 
WHERE device.Id = 100;

我不确定如何在我的投影中显示设备是否超频。

2 个答案:

答案 0 :(得分:1)

您想使用左外连接 - 并在on子句中添加功能名称' overclock'。然后,使用案例陈述来确定该记录是否存在 - 并返回'是'当它发生的时候 - 并且'否'因为它什么时候没有。另外,为了清晰起见,我缩进了您的查询:

SELECT  device.Id, 
    owner.Name, 
    CASE 
        WHEN Capability.ID IS NULL THEN 'NO'
        ELSE 'YES' 
    END as [hasOverclock]
FROM Device device
LEFT OUTER JOIN Owner 
    on Owner.Id = Device.ownerId
INNER JOIN DeviceType 
    on DeviceType.Id = Device.DeviceTypeId
INNER JOIN TypeCapability 
    on TypeCapability.DeviceTypeId = DeviceType.Id
LEFT OUTER JOIN Capability 
    on Capability.Id = TypeCapability.CapabilityId 
    AND Capability.CapabilityName = 'Overclock'
WHERE device.Id = 100;

请告知我这是否有效,我会编辑我的答案。

注意:您需要在ON子句中保持功能名称检查(对于'超频')而不是在where子句中。如果它在where子句中,则您将省略完全不加入的记录(这与使用内部联接相同)。外连接是唯一一次将条件从where子句移动到on子句会影响结果集。

修改

由于数据库的结构,我认为最好只使用以下查询。由于' OverClock' capabilityID不会改变 - 因为您的查询特定于此值,我认为在查询中使用它更有意义,使其更简单:

DECLARE @OverClockCapabilityID int = 55

SELECT  D.Id as [DeviceID],
    O.Name as [OwnerName],
    CASE 
        WHEN TC.ID IS NULL THEN 'NO'
        ELSE 'YES'
    END AS [HasOverClock]
FROM Device D      //Should only be one record
JOIN DeviceType DT  //Should only be one record
    ON D.DeviceTypeID = DT.ID
LEFT OUTER JOIN Type_Capability TC  //Should only be one record, assuming you don't have duplicate records in this join table (which you shouldn't)
    ON DT.ID = TC.DeviceTypeID
    AND TC.CapabilityID = @OverClockCapabilityID //This eliminates other capabilities, which we don't care about in this query
LEFT OUTER JOIN Owner O
    ON D.OwnerID = O.ID

我希望这适合你!

答案 1 :(得分:1)

您需要汇总:

SELECT D.ID as DeviceID, O.Name as OwnerName,
       (CASE WHEN SUM(CASE WHEN C.CapabilityName = 'overclock' THEN 1 ELSE 0 END) > 0
             THEN 1
             ELSE 0
        END) as OverclockFlag
FROM Device D JOIN DeviceType
     DT
     ON D.DeviceTypeID = DT.ID LEFT OUTER JOIN
     Type_Capability TC 
     ON DT.ID = TC.DeviceTypeID LEFT OUTER JOIN
     Capability C
     ON TC.CapabilityID = C.ID LEFT OUTER JOIN
     Owner O
     ON D.OwnerID = O.ID
WHERE Device.ID = 100 
GROUP BY D.ID, O.Name ;

请注意,您要删除where并为所有设备ID执行此操作。