所以,我不得不说,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 = ??
如何在“A”“B”和“C”的所有3种不同的id设备上过滤这个。 显然,我做不到 由于一个单元不能等于2个不同的值,所以Equipment.IdEquipment = 1和Equipment.IdEquipment = 2。 我也做不到 在哪里,Equipment.IdEquipment = 1或Equipment.IdEquipment = 2,因为使用OR意味着任何持有至少一种可能性的用户将被视为有效结果,并且我正在寻找一个拥有所有3种不同设备的用户情况下。
起初我假设我必须使用表设备创建多个内部联接,使用别名,多次使用我可能拥有的设备上的过滤器,并使用不同过滤器的每个别名。但后来我的代码主管过来告诉我要忘掉它,因为他说随着越来越多的过滤器被添加会变得太昂贵(虽然他没有给我更好的选择......)
答案 0 :(得分: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,可以从查询中删除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
此外,一些别名使其更易于阅读:
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
答案 1 :(得分: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