2015-12-18 87 views
1

我具有可以或可以不具有取決於是否就是已被銷售的所有者的設備實體:檢查存在

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

Owner 
===== 
Id 
Name 

每種類型的設備都可以有不同的能力,而每個功能都可以映射到多個類型,所以我有一個聯結表。

DeviceType 
==== 
Id 
ModelNum 

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

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

我想編寫一個查詢,如果它存在,將返回該設備的所有者,以及設備是否有名爲「超頻」的能力。

我有以下幾點:

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; 

我不確定我如何面設備是否在我的投影超頻。

+0

請準備http://sqlfiddle.com樣本數據和所需的輸出。提供準確答案並避免猜測會容易得多。 – lad2025

回答

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。

+0

工程像一個魅力,但我承認我不太明白如何。我發現我們正在拼湊聚合,但SUM和'CASE'的內幕是什麼?我們在分組過程中評估每條記錄? –

+0

@MisterEpic。 。 。它正在用「超頻」值來計算功能的數量。 '> 0'只是說有一些。這可以在'on'子句中,但是這種方法可以更容易地推廣到更多功能。 –

1

你想使用一個左外連接 - 並在on子句中添加功能名稱'overclock'。然後,使用case語句來確定該記錄是否存在 - 並在其返回時返回「是」,否則返回「否」。另外,我縮進查詢爲清楚:

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子句影響結果集的唯一時間。

編輯:

因爲你的數據庫的結構,我認爲這是最好只使用下面的查詢。因爲「超頻」 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

每個功能都有一條記錄回來。當我回到我的辦公室時,我會創作一個小提琴。謝謝! –

+0

@MisterEpic好的,我更新了答案。在創建小提琴之前嘗試一下 - 我認爲它會起作用。 –