首先 - 为模糊标题道歉,我找不到更好的标题。
我有以下结构的表格(简化):
EmpID DeptID
1 1
1 2
2 1
3 2
4 5
5 2
此表代表多对多关系。
我有兴趣找到与特定DeptID组相关的所有EmpID,例如我想要所有与DeptID 1,2和3相关的EmpID。请注意它是AND关系而不是OR关系。对于我的情况,EmpID可能与除1,2和3之外的其他DeptID有关,因为它是有效的答案。
我感兴趣的DeptID数量有所变化(即我可能想要与DeptID 3和5相关的EmpID,或者我可能想要与DepID 2,3,4,5,6,7相关的EmpID)
当我尝试解决此问题时,我发现自己要么为每个DepID创建一个JOIN,要么为每个DeptID创建一个子查询。这意味着我必须根据我正在测试的DeptID数量生成一个新查询。我显然更喜欢使用参数或参数集进行静态查询。
我正在研究SQL Server和MySQL(并行开发两个版本的代码)。
有什么想法吗?
答案 0 :(得分:14)
我假设你想找到属于所有指定部门的员工,而不只是那些部门 ANY 的员工,这是一个更容易查询。
SELECT EmpID
FROM mytable t1
JOIN mytable t2 ON t1.EmpID = t2.EmpID AND t2.DeptID = 2
JOIN mytable t3 ON t2.EmpID = t3.EmpID AND t3.DeptID = 3
WHERE DeptID = 1
我将抢占使用聚合的不可避免的建议:
SELECT EmpID
FROM mytable
WHERE DeptID IN (1,2,3)
GROUP BY EmpID
HAVING COUNT(1) = 3
抵制诱惑。它显着慢。类似的情况出现在SQL Statement - “Join” Vs “Group By and Having”中,第二个版本在第二个版本中,慢了20倍。
答案 1 :(得分:3)
我从以下的东西开始:
SELECT EmpID, COUNT(*) AS NumDepts
FROM thetable
WHERE DeptID IN (1, 2, 3)
GROUP BY EmpId
HAVING COUNT(*) == 3
当然,最后一行中的3将始终是您正在检查的部门ID序列的长度(因此对于(2,3,4,5,6,7)
它将是6)。这是表达“与所有这些部门相关的员工”的一种自然方式。
编辑:我在另一个关于性能问题的答案中看到了一个注释 - 我在SQLite和PostgreSQL中尝试了这种方法,并使用了适当的索引,并且看起来它表现良好且适当使用了所有所述索引;在MySQL 5.0中,我必须承认性能无处可寻。
我怀疑(没有机会在更多的引擎上对此进行基准测试;-)其他非常好的SQL引擎(例如SQL Server 2008,Oracle,IBM DB2,新的开源Ingres ......)也将很好地优化这个查询,而其他平庸的(不能想到任何在MySQL附近的人气)都不会。
所以,毫无疑问,你最喜欢的答案将取决于你真正关心的引擎(这让我回到了十多年前的时间,当时我的职责包括管理团队,该团队维护了一个应该提供的组件 - 对超过六个不同的引擎进行查询 - 谈论噩梦般的工作......! - 。)。