Select Distinct on Inner Join Query filtering by multiple values on a single column?

18,157
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

If you really just need the user ID, you can drop the Users and Licenses tables from your 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

Also, some aliases makes it easier to read:

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
Share:
18,157
Hobbes
Author by

Hobbes

Updated on June 04, 2022

Comments

  • Hobbes
    Hobbes almost 2 years

    So, i have to say, SQL is by far my weakest side as a developer. Perhaps what i'm trying to accomplish is pretty easy. I have something like this (It's not the real model, but in order to make it simple to understand without wasting too much time explaining it, i've come up with an example that mimics exactly the table relations i have to use). On one hand, a table, let's call it, "Users". Columns such as a primary key "UserId", "UserName", and so on.

    Next, another Table, "Licenses". Relates 1:N with user, each license belongs to a single user, a user may have multiple licenses. So, we'd have a PK IdLicense, a FK IdUser, and so on.

    Next, a table called "Equipments". here we have defined different equipments. IdEquipment, EquipmentName. Not much more to say about it.

    Lastly, a table that creates a N:M relation between "Licenses" and "Equipments". when a user defines a license, they can specify the different equipments that licence allows them to manipulate. So, a license can relate to several equipments, and a piece of equipment can relate to multiple licenses.

    The real deal comes here. I've been ordered to implement some kind of search system that allows you to get users based on the equipment they are qualified to handle.It's possible to make a multiple selection, so that you search for users that are qualified to handle equipment "A", "B" and "C". For example, we have 2 users, James and, Dave. James has 2 licenses, Dave has one. James is qualified to use machines "A" and "D" on his first license, "B" and "C" on the second one. Dave is qualififed to handle equipment type "B" and "C" on his only license. If someone tries to search for users being able to handle equipment "A","B" AND "C", only James would be the returning record.

    So far i assumed i'd have to do something like

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

    How can i filter this on the all 3 different idEquipments for "A" "B" and "C".? Obviously, i can't make WHERE Equipment.IdEquipment = 1 and Equipment.IdEquipment = 2 since a cell can't be equal to 2 different values. Neither i can do WHERE Equipment.IdEquipment = 1 or Equipment.IdEquipment = 2 since using an OR would mean that any user holding at least ONE of the possibilities would be considered a valid result, and i'm looking for one that has ALL 3 different equipments on this case.

    At first I assumed I'd have to create multiple inner joins with the table equipment, using alias, doing it as many times as filters on equipment i may have, and using each alias with a different filter. But then my code supervisor came by and told me to forget about it, since he said that would render too costly as more and more filters where added (though he gave me no better alternative...)

  • Hobbes
    Hobbes over 11 years
    Thanks, but, wouldn't that return any users having 3 equipments, nevermind what they are, as long as one of them is "A","B","C"?. For example, someone is allowed to handle "A" "F" and "T". That person would be among the results, but i want those who can handle "A" "B" "C". IF they can also handle more stuff is ok, but they MUST be able to handle all of those included in the filter, not just one of them...
  • Hobbes
    Hobbes over 11 years
    ok, forget it, i didnt have my morning coffee yet, lol. thanks a lot!