2012-10-31 6 views
5

Also, ich muss sagen, SQL ist bei weitem meine schwächste Seite als Entwickler. Vielleicht ist das, was ich zu erreichen versuche, ziemlich einfach. Ich habe so etwas (es ist nicht das reale Modell, aber um es verständlich zu machen, ohne zu viel Zeit damit zu verschwenden, es zu erklären, habe ich ein Beispiel gefunden, das genau die Tabellenrelationen nachahmt, die ich benutzen muss). Auf der einen Seite, eine Tabelle, nennen wir es "Benutzer". Spalten wie ein Primärschlüssel "UserId", "UserName" und so weiter.Select Distinct auf innerem Join Abfragefilterung nach mehreren Werten in einer einzelnen Spalte?

Als nächstes eine weitere Tabelle, "Lizenzen". Verwandt 1: N mit Benutzer, jede Lizenz gehört einem einzelnen Benutzer, ein Benutzer kann mehrere Lizenzen haben. Also hätten wir eine PK IdLicense, einen FK IdUser und so weiter.

Als nächstes eine Tabelle namens "Ausrüstungen". hier haben wir verschiedene Ausrüstungen definiert. IdEquipment, Ausrüstungsname. Nicht viel mehr darüber zu sagen.

Schließlich eine Tabelle, die eine N: M-Beziehung zwischen "Lizenzen" und "Ausrüstungen" erstellt. Wenn ein Benutzer eine Lizenz definiert, kann er die verschiedenen Geräte angeben, die durch die Lizenz manipuliert werden können. Eine Lizenz kann sich also auf mehrere Geräte beziehen, und ein Gerät kann sich auf mehrere Lizenzen beziehen.

Der echte Deal kommt hier. Ich wurde beauftragt, ein Suchsystem zu implementieren, das es Ihnen ermöglicht, Benutzer basierend auf der Ausrüstung zu erhalten, für die sie qualifiziert sind. Es ist möglich, eine Mehrfachauswahl zu treffen, so dass Sie nach Benutzern suchen, die für die Ausrüstung qualifiziert sind "," B "und" C ". Zum Beispiel haben wir 2 Benutzer, James und Dave. James hat 2 Lizenzen, Dave hat einen. James ist qualifiziert, Maschinen "A" und "D" auf seiner ersten Lizenz, "B" und "C" auf der zweiten Lizenz zu verwenden. Dave ist berechtigt, auf seiner einzigen Lizenz den Gerätetyp "B" und "C" zu verwenden. Wenn jemand versucht, nach Benutzern zu suchen, die mit den Geräten "A", "B" und "C" umgehen können, wäre nur James der zurückkehrende Rekord.

Bisher ging ich davon aus ich etwas zu tun haben würde wie

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

Wie kann ich dies auf die alle 3 verschiedenen idEquipments Filter für „A“ „B“ und „C“.? Offensichtlich kann ich WHERE Equipment.IdEquipment = 1 und Equipment.IdEquipment = 2 nicht machen, da eine Zelle nicht gleich 2 verschiedene Werte sein kann. Weder ich kann WHERE Equipment.IdEquipment = 1 oder Equipment.IdEquipment = 2, da die Verwendung eines OR bedeutet, dass jeder Benutzer, der mindestens eine der Möglichkeiten hält, als ein gültiges Ergebnis betrachtet werden würde, und ich suche nach einem, das hat ALLE 3 verschiedene Ausrüstungen auf diesem Fall.

Zuerst nahm ich an, dass ich mehrere interne Joins mit der Tischausrüstung erstellen musste, indem ich alias verwendete, so oft wie Filter an Geräten verwendete und jeden Alias ​​mit einem anderen Filter verwendete. Aber dann kam mein Code Supervisor durch und sagte mir, es zu vergessen, da sagte er, dass machen würde zu teuer, da immer mehr Filter, wo hinzugefügt (obwohl er mir keine bessere Alternative gab ...)

Antwort

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 

Wenn Sie wirklich nur die Benutzer-ID benötigen, können Sie die Users und Licenses Tabellen aus der Abfrage fallen können:

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 

auch einige Aliase macht es leichter zu lesen:

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

Danke, aber, würde das keinen Benutzer zurückgeben, der 3 Ausrüstungen hat, vergiss, was sie sind, solange einer von ihnen "A", "B", "C" ist.Zum Beispiel darf jemand "A" "F" und "T" behandeln. Diese Person würde zu den Ergebnissen gehören, aber ich möchte diejenigen, die mit "A" "B" "C" umgehen können. Wenn sie auch mehr Sachen handhaben können, ist das ok, aber sie MÜSSEN in der Lage sein, all die im Filter enthaltenen zu behandeln, nicht nur eine von ihnen ... – Hobbes

+0

ok, vergiss es, ich hatte meinen Morgenkaffee noch nicht, lol. Danke vielmals! – 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 
Verwandte Themen