13

首先 - 为模糊的标题道歉,我找不到更好的。

我有以下结构的表(简化):

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(并行开发我的代码的两个版本)。

有任何想法吗?

4

2 回答 2

14

我假设您想查找所有指定部门的员工,而不仅仅是任何部门的员工,这是一个更容易查询。

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 语句中出现了与此类似的场景 - “Join” Vs “Group By and Have”</a>,第二个版本在那一秒内慢了大约 20 倍

我还建议您查看AppDevelopers 所犯的数据库开发错误

于 2009-06-28T05:14:12.497 回答
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 的)不会。

因此,毫无疑问,您最喜欢的答案将取决于您真正关心的引擎(这让我回到了十多年前,当时我的职责包括管理维护一个组件的团队,该组件应该提供性能良好的查询超过六种不同的引擎——谈论噩梦般的工作......!-)。

于 2009-06-28T05:18:09.200 回答