2012-10-31 27 views
5

所以,我不得不说,SQL是开发者迄今为止最弱的一面。也许我想要完成的事情很简单。我有这样的东西(这不是真正的模型,但为了使它容易理解而不浪费太多时间来解释它,我想出了一个模仿我必须使用的表格关系的例子)。 一方面,一张桌子,我们称之为“用户”。诸如主键“UserId”,“UserName”等的列。通过单个列上的多个值选择不同内部联接查询?

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

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

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

真正的交易来到这里。我已被命令实施某种搜索系统,以便您可以根据他们有资格处理的设备获取用户。可以进行多项选择,以便搜索有资格处理设备的用户“A “,”B“和”C“。例如,我们有2个用户,James和Dave。詹姆斯有两个执照,戴夫有一个。詹姆斯有资格在第一个许可证上使用机器“A”和“D”,第二个许可证上使用“B”和“C”。戴夫的唯一许可证是处理设备类型“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个不同idEquipments过滤此? 显然,我不能使 WHERE Equipment.IdEquipment = 1和Equipment.IdEquipment = 2,因为单元格不能等于2个不同的值。 既没有我可以做 其中Equipment.IdEquipment = 1或Equipment.IdEquipment = 2,因为使用或将意味着任何持有至少一种可能性的用户将被视为有效的结果,我正在寻找一个有这种情况下所有3种不同的设备。

起初我假设我必须用表设备创建多个内部联接,使用别名,尽可能多地使用设备上的过滤器,并将每个别名与不同的过滤器一起使用。但后来我的代码上司走过来,告诉我这件事给忘了,因为他说,这将使得成本太高的地方添加更多的过滤器(虽然他给了我没有更好的选择......)

回答

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 
+0

谢谢,但是,如果只有其中一个是“A”,“B”,“C”,那么不会返回任何拥有3个设备的用户,也不会知道他们是什么。例如,允许某人处理“A”“F”和“T”。那个人会是结果之一,但我希望那些能够处理“A”“B”“C”的人。如果他们也可以处理更多的东西是可以的,但他们必须能够处理过滤器中包含的所有内容,而不仅仅是其中之一... – Hobbes

+0

好吧,忘记它吧,我还没有喝过早晨的咖啡,哈哈。非常感谢! – 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 
相关问题