13

まず、あいまいなタイトルで申し訳ありません。これ以上のタイトルが見つかりませんでした。

次の構造のテーブルがあります(簡略化):

EmpID DeptID

1     1
1     2
2     1
3     2
4     5
5     2

このテーブルは、多対多の関係を表しています。

たとえば、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 を作成するか、DepID ごとにサブクエリを作成する必要があります。これは、テスト対象の DeptID の数ごとに新しいクエリを生成する必要があることを意味します。私は明らかに、パラメーターまたはパラメーターのセットを使用した静的クエリを使用することを好みます。

私は SQL Server と MySQL の両方で作業しています (コードの 2 つのバージョンを並行して開発しています)。

何か案は?

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 ステートメント - 「結合」 対 「グループ化と所有」</a> で発生し、2 番目のバージョンはその秒で約20 倍遅くなりました。

また、 AppDevelopers が作成した Database Development Mistakes もご覧になることをお勧めします

于 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 になります)。これは、「これらすべての部門に接続されている従業員」を表現する 1 つの自然な方法です。

編集:パフォーマンスの問題に関する別の回答にメモがあります-適切なインデックスを使用してSQLiteとPostgreSQLでこのアプローチを試しましたが、パフォーマンスが良好で、上記のすべてのインデックスを適切に使用しているようです。そしてMySQL 5.0では、パフォーマンスがどこにも及ばなかったことを認めなければなりません.

(これを無数のエンジンでベンチマークする機会がなければ;-) 他の本当に優れた SQL エンジン (SQL Server 2008、Oracle、IBM DB2、新しいオープンソースの Ingres など...) もこのクエリを最適化するのではないかと思います。まあ、他の平凡なもの (MySQL に近い人気のあるものは考えられません) はそうではありません。

したがって、あなたの好みの答えは、あなたが本当に気にかけているエンジンに依存することは間違いありません (これは 10 年以上前のことで、私の責任には、パフォーマンスの高いクエリを提供するはずのコンポーネントを維持するチームの管理が含まれていたときのことです)。半ダース以上の異なるエンジン -- 悪夢のような仕事について話してください...!-)。

于 2009-06-28T05:18:09.200 に答える