5

所以,我不得不说,到目前为止,SQL 是我作为开发人员最弱的一面。也许我想要完成的事情很容易。我有这样的东西(它不是真正的模型,但为了使其易于理解而不浪费太多时间解释它,我想出了一个完全模仿我必须使用的表关系的示例)。一方面,一个表,我们称之为“用户”。主键“UserId”、“UserName”等列。

接下来是另一个表,“许可证”。1:N 与用户相关,每个许可证属于一个用户,一个用户可能有多个许可证。因此,我们将有一个 PK IdLicense、一个 FK IdUser 等等。

接下来是一个名为“设备”的表。在这里,我们定义了不同的设备。IdEquipment,设备名称。没什么好说的了。

最后,在“许可证”和“设备”之间创建 N:M 关系的表。当用户定义许可证时,他们可以指定许可证允许他们操作的不同设备。因此,一个许可证可以关联多个设备,而一个设备可以关联多个许可证。

真正的交易来了。我受命实施某种搜索系统,允许您根据他们有资格操作的设备来获取用户。可以进行多项选择,以便您搜索有资格操作设备的用户“A ”、“B”和“C”。例如,我们有 2 个用户,James 和 Dave。詹姆斯有两张执照,戴夫有一张。James 有资格在他的第一个许可证上使用机器“A”和“D”,在第二个许可证上可以使用机器“B”和“C”。Dave 有资格在他的唯一执照上处理设备类型“B”和“C”。如果有人尝试搜索能够处理设备“A”、“B”和“C”的用户,则只有 James 将是返回记录。

到目前为止,我认为我必须做类似的事情

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 个不同的 idEquipments 上过滤这个?显然,我不能让 WHERE Equipment.IdEquipment = 1 和 Equipment.IdEquipment = 2 因为一个单元格不能等于 2 个不同的值。我也不能这样做 WHERE Equipment.IdEquipment = 1 或 Equipment.IdEquipment = 2 因为使用 OR 意味着任何持有至少一种可能性的用户都将被视为有效结果,我正在寻找一个拥有 ALL 3这种情况下的不同设备。

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

4

2 回答 2

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,您可以从查询中删除UsersLicenses表:

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
于 2012-10-31T01:11:10.193 回答
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
于 2013-11-14T09:05:22.317 回答