选择内部连接上的区别查询按单个列上的多个值进行筛选?

Hob*_*bes 5 sql distinct where

所以,我不得不说,SQL是迄今为止我作为开发人员最薄弱的一面.也许我想要完成的事情很简单.我有这样的东西(这不是真正的模型,但为了使它易于理解而不浪费太多时间解释它,我想出了一个模仿我必须使用的表关系的例子).一方面,一个表,我们称之为"用户".列,例如主键"UserId","UserName"等.

接下来,另一个表,"许可证".与用户相关1:N,每个许可属于单个用户,用户可能有多个许可.所以,我们有一个PK IdLicense,一个FK IdUser等等.

接下来,一个名为"Equipments"的表.在这里我们定义了不同的设备.IdEquipment,EquipmentName.关于它的说法不多.

最后,在"许可证"和"设备"之间创建N:M关系的表.当用户定义许可证时,他们可以指定许可证允许他们操纵的不同设备.因此,许可证可以涉及多个设备,并且一个设备可以涉及多个许可证.

真正的交易来到这里.我已被命令实施某种搜索系统,允许您根据他们有资格处理的设备获取用户.可以进行多项选择,以便您搜索有资格处理设备的用户"A ","B"和"C".例如,我们有2个用户,James和Dave.詹姆斯有两个执照,戴夫有一个.詹姆斯有资格在他的第一张牌照上使用机器"A"和"D",在第二张牌照上使用"B"和"C".Dave有资格在他的唯一许可证上处理"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 = ??
Run Code Online (Sandbox Code Playgroud)

如何在"A""B"和"C"的所有3种不同的idEquipments上过滤这个.显然,我不能使WHERE Equipment.IdEquipment = 1和Equipment.IdEquipment = 2,因为一个单元格不能等于2个不同的值.我不能做WHERE Equipment.IdEquipment = 1或Equipment.IdEquipment = 2,因为使用OR意味着任何持有至少一种可能性的用户将被视为有效结果,并且我正在寻找一个拥有ALL 3的用户这种情况下的设备不同.

起初我假设我必须使用表设备创建多个内连接,使用别名,多次使用我可能拥有的设备上的过滤器,并使用每个别名使用不同的过滤器.但后来我的代码主管过来告诉我要忘记它,因为他说随着越来越多的过滤器的添加会变得太昂贵(尽管他没有给我更好的选择......)

Red*_*ter 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
Run Code Online (Sandbox Code Playgroud)

如果您确实只需要用户 ID,则可以从查询中删除Users和表:Licenses

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
Run Code Online (Sandbox Code Playgroud)

此外,一些别名使其更易于阅读:

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
Run Code Online (Sandbox Code Playgroud)