2012-10-31 29 views
5

所以,我不得不說,SQL是開發者迄今爲止最弱的一面。也許我想要完成的事情很簡單。我有這樣的東西(這不是真正的模型,但爲了使它容易理解而不浪費太多時間來解釋它,我想出了一個模仿我必須使用的表格關係的例子)。 一方面,一張桌子,我們稱之爲「用戶」。諸如主鍵「UserId」,「UserName」等的列。通過單個列上的多個值選擇不同內部聯接查詢?

接下來,另一個表,「許可證」。將1:N與用戶相關聯,每個許可證屬於單個用戶,用戶可能擁有多個許可證。所以,我們有一個PK IdLicense,一個FK IdUser,等等。

接下來,一個名爲「設備」的表。這裏我們定義了不同的設備。 IdEquipment,設備名稱。沒什麼可說的。

最後,在「許可證」和「設備」之間創建N:M關係的表。當用戶定義許可證時,他們可以指定許可證允許他們操作的不同設備。所以,許可證可以涉及多個設備,一件設備可以涉及多個許可證。

真正的交易來到這裏。我已被命令實施某種搜索系統,以便您可以根據他們有資格處理的設備獲取用戶。可以進行多項選擇,以便搜索有資格處理設備的用戶「A 「,」B「和」C「。例如,我們有2個用戶,James和Dave。詹姆斯有兩個執照,戴夫有一個。詹姆斯有資格在第一個許可證上使用機器「A」和「D」,第二個許可證上使用「B」和「C」。戴夫的唯一許可證是處理設備類型「B」和「C」的資格。如果有人試圖搜索能夠處理設備「A」,「B」和「C」的用戶,則只有詹姆斯將成爲返回記錄。

到目前爲止,我認爲我必須做這樣的事情

SELECT DISTINCT IdUser 
FROM Users 
INNER JOIN Licenses 
    ON Licenses.IdUser = Users.idUser 
INNER JOIN LicensesEquipments 
    ON LicensesEquipments.IdLicense = Licenses.IdLicense 
INNER JOIN Equipment 
    ON Equipment.IdEquipment = LicensesEquipments.IdEquipment 

WHERE Equipment.IdEquipment = ?? 

我怎麼能對「A」「B」和「C」的所有3個不同idEquipments過濾此? 顯然,我不能使 WHERE Equipment.IdEquipment = 1和Equipment.IdEquipment = 2,因爲單元格不能等於2個不同的值。 既沒有我可以做 其中Equipment.IdEquipment = 1或Equipment.IdEquipment = 2,因爲使用或將意味着任何持有至少一種可能性的用戶將被視爲有效的結果,我正在尋找一個有這種情況下所有3種不同的設備。

起初我假設我必須用表設備創建多個內部聯接,使用別名,儘可能多地使用設備上的過濾器,並將每個別名與不同的過濾器一起使用。但後來我的代碼上司走過來,告訴我這件事給忘了,因爲他說,這將使得成本太高的地方添加更多的過濾器(雖然他給了我沒有更好的選擇......)

回答

4
SELECT Users.idUser 
FROM Users 
INNER JOIN Licenses ON Licenses.IdUser = Users.idUser 
INNER JOIN LicensesEquipments ON LicensesEquipments.IdLicense = Licenses.IdLicense 
INNER JOIN Equipment ON Equipment.IdEquipment = LicensesEquipments.IdEquipment 
WHERE Equipment.IdEquipment IN ('A', 'B', 'C') 
GROUP BY IdUser 
HAVING COUNT(DISTINCT Equipment.IdEquipment) = 3 <--must be # of unique items in IN clause 

如果你真的只需要用戶ID,您可以從查詢刪除UsersLicenses表:

SELECT Licenses.IdUser 
FROM Licenses 
INNER JOIN LicensesEquipments ON LicensesEquipments.IdLicense = Licenses.IdLicense 
WHERE LicensesEquipments.IdEquipment in ('A', 'B', 'C') 
GROUP BY Licenses.IdUser 
HAVING COUNT(DISTINCT LicensesEquipments.IdEquipment) = 3 

此外,一些別名使得它更易於閱讀:

SELECT l.IdUser 
FROM Licenses l 
INNER JOIN LicensesEquipments le ON le.IdLicense = l.IdLicense 
WHERE le.IdEquipment in ('A', 'B', 'C') 
GROUP BY l.IdUser 
HAVING COUNT(DISTINCT le.IdEquipment) = 3 
+0

謝謝,但是,如果只有其中一個是「A」,「B」,「C」,那麼不會返回任何擁有3個設備的用戶,也不會知道他們是什麼。例如,允許某人處理「A」「F」和「T」。那個人會是結果之一,但我希望那些能夠處理「A」「B」「C」的人。如果他們也可以處理更多的東西是可以的,但他們必須能夠處理過濾器中包含的所有內容,而不僅僅是其中之一... – Hobbes

+0

好吧,忘記它吧,我還沒有喝過早晨的咖啡,哈哈。非常感謝! – Hobbes

0
SELECT l.IdUser 
FROM Licenses l 
INNER JOIN LicensesEquipments le ON le.IdLicense = l.IdLicense 
WHERE le.IdEquipment in (`enter code here`'A', 'B', 'C') 
GROUP BY l.IdUser 
HAVING COUNT(DISTINCT le.IdEquipment) = 3 
相關問題