2012-10-31 14 views
5

Quindi, devo dire, SQL è di gran lunga il mio lato più debole come sviluppatore. Forse quello che sto cercando di realizzare è abbastanza facile. Ho qualcosa di simile (non è il modello reale, ma per renderlo semplice da capire senza sprecare troppo tempo a spiegarlo, ho trovato un esempio che riproduce esattamente le relazioni del tavolo che devo usare). Da un lato, un tavolo, chiamiamolo "Utenti". Colonne come una chiave primaria "UserId", "UserName" e così via.Seleziona Distinto su collegamento interno Query che filtra per più valori su una singola colonna?

Successivamente, un'altra tabella "Licenze". Riguarda 1: N con utente, ogni licenza appartiene a un singolo utente, un utente può avere più licenze. Quindi, avremmo un IdLicense PK, un IdUser FK e così via.

Successivamente, una tabella denominata "Attrezzature". qui abbiamo definito diverse attrezzature. IdEquipment, EquipmentName. Non c'è molto altro da dire al riguardo.

Infine, una tabella che crea una relazione N: M tra "Licenze" e "Attrezzature". quando un utente definisce una licenza, può specificare le diverse apparecchiature che la licenza consente loro di manipolare. Quindi, una licenza può riguardare diverse attrezzature e un pezzo di equipaggiamento può riguardare più licenze.

Il vero affare arriva qui. Mi è stato ordinato di implementare una sorta di sistema di ricerca che consente di ottenere utenti basati sull'attrezzatura che sono qualificati per gestire. È possibile effettuare una selezione multipla, in modo da cercare utenti qualificati per gestire le apparecchiature "A "," B "e" C ". Ad esempio, abbiamo 2 utenti, James e, Dave. James ha 2 licenze, Dave ne ha una. James è qualificato per usare le macchine "A" e "D" sulla sua prima licenza, "B" e "C" sulla seconda. Dave è abilitato a gestire le apparecchiature di tipo "B" e "C" sulla sua unica licenza. Se qualcuno cerca di cercare utenti in grado di gestire l'equipaggiamento "A", "B" E "C", solo James sarebbe il record di ritorno.

Finora ho pensato che avrei dovuto fare qualcosa di simile

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 = ?? 

Come posso filtrare questo sui tutti i 3 idEquipments diversi per "A" "B" e "C".? Ovviamente, non posso creare DOVE Equipment.IdEquipment = 1 e Equipment.IdEquipment = 2 poiché una cella non può essere uguale a 2 valori diversi. Né posso fare DOVE Equipment.IdEquipment = 1 o Equipment.IdEquipment = 2 dal momento che utilizzare un OR significherebbe che qualsiasi utente che possiede almeno UNA delle possibilità sarebbe considerato un risultato valido, e sto cercando uno che abbia TUTTE le 3 diverse attrezzature in questo caso.

Inizialmente ho pensato che avrei dovuto creare più join interni con l'apparecchiatura da tavolo, usando l'alias, facendolo tutte le volte che potevo avere i filtri sulle apparecchiature che potevo avere e usando ogni alias con un filtro diverso. Ma poi il mio supervisore codice è venuto da me e ha detto di non pensarci più, dal momento che ha detto che renderebbe troppo costoso, come sempre più filtri in cui aggiunti (anche se mi ha dato alcuna alternativa migliore ...)

risposta

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 

Se si ha realmente bisogno solo l'ID utente, è possibile eliminare le tabelle Users e Licenses dalla query:

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 

Inoltre, alcuni alias rende più facile da leggere:

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

Grazie, ma non restituirebbe alcun utente con 3 apparecchiature, non importa quali siano, purché uno di essi sia "A", "B", "C" ?.Ad esempio, a qualcuno è consentito gestire "A" "F" e "T". Quella persona sarebbe tra i risultati, ma voglio quelli che possono gestire "A" "B" "C". Se possono anche gestire più roba è ok, ma DEVONO essere in grado di gestire tutti quelli inclusi nel filtro, non solo uno di loro ... – Hobbes

+0

ok, lascia perdere, non ho ancora il mio caffè mattutino, lol. molte grazie! – 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 
Problemi correlati