2009-06-28 36 views
13

Đầu tiên - xin lỗi cho tiêu đề mờ, tôi không thể tìm thấy cái nào tốt hơn.SQL: Nhiều bảng và truy vấn

Tôi có bảng với cấu trúc (đơn giản hóa) như sau:

EmpID DeptID 

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

Bảng này đại diện cho một mối quan hệ nhiều-nhiều.

Tôi quan tâm đến việc tìm tất cả các EmpID có liên quan đến nhóm DeptID cụ thể, ví dụ tôi muốn tất cả các EmpID có liên quan đến DeptID 1, 2 và 3. Xin lưu ý đó là mối quan hệ AND chứ không phải HOẶC mối quan hệ. Đối với trường hợp của tôi, EmpID có thể liên quan đến các DeptID bổ sung bên cạnh 1, 2 và 3 để nó là một câu trả lời hợp lệ.

Số lượng DeptID tôi quan tâm đến thay đổi (nghĩa là tôi có thể muốn EmpID liên quan đến cả hai DeptID 3 và 5, hoặc tôi có thể muốn EmpID liên quan đến DepIDs 2, 3, 4, 5, 6, 7).

Khi tôi cố gắng tiếp cận sự cố này, tôi thấy mình hoặc tạo JOIN mỗi DepID hoặc truy vấn con trên mỗi DeptID. Điều này có nghĩa là tôi phải tạo một truy vấn mới cho mỗi số DeptID mà tôi đang thử nghiệm. Tôi rõ ràng sẽ thích có một truy vấn tĩnh với một tham số hoặc tập hợp các tham số.

Tôi đang làm việc trên cả SQL Server và MySQL (phát triển song song với hai phiên bản mã của tôi).

Bất kỳ ý tưởng nào?

Trả lời

14

tôi giả sử bạn muốn tìm nhân viên có trong ALL của các phòng ban theo quy định và không chỉ là người lao động có trong BẤT CỨ của các phòng ban, mà là một truy vấn dễ dàng hơn.

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 

Tôi sẽ chặn trước đề nghị không thể tránh khỏi rằng sẽ đến sử dụng kết hợp:

SELECT EmpID 
FROM mytable 
WHERE DeptID IN (1,2,3) 
GROUP BY EmpID 
HAVING COUNT(1) = 3 

Chống lại sự cám dỗ đó. Đó là đáng kể chậm hơn. Một kịch bản tương tự với điều này xuất hiện trong SQL Statement - “Join” Vs “Group By and Having” và phiên bản thứ hai là, trong giây phút đó, khoảng hai mươi lần chậm hơn.

Tôi cũng khuyên bạn nên xem Database Development Mistakes Made by AppDevelopers.

3

tôi muốn bắt đầu từ cái gì đó như:

SELECT EmpID, COUNT(*) AS NumDepts 
FROM thetable 
WHERE DeptID IN (1, 2, 3) 
GROUP BY EmpId 
HAVING COUNT(*) == 3 

tất nhiên, rằng 3 trong dòng cuối cùng sẽ luôn luôn được chiều dài của chuỗi các ids bộ phận bạn đang kiểm tra (để cho (2,3,4,5,6,7) nó sẽ là 6). Đây là một cách tự nhiên để thể hiện "nhân viên kết nối với tất cả các phòng ban".

Chỉnh sửa: Tôi thấy một câu trả lời trong câu trả lời khác về các vấn đề hiệu suất - Tôi đã thử phương pháp này trong SQLite và PostgreSQL, với các chỉ số thích hợp và có vẻ như nó hoạt động tốt và sử dụng thích hợp tất cả các chỉ mục đã nói; và trong MySQL 5.0, nơi tôi phải thừa nhận hiệu suất là hư không tốt.

Tôi nghi ngờ (không có cơ hội để đánh giá điều này trên hơn một trăm động cơ ;-) mà các công cụ SQL thực sự tốt khác (như SQL Server 2008, Oracle, IBM DB2, Ingres nguồn mở mới ...) cũng sẽ tối ưu hóa truy vấn này tốt, trong khi những người tầm thường khác (không thể nghĩ ra bất kỳ sự phổ biến nào ở bất kỳ đâu gần với MySQL). Vì vậy, không nghi ngờ gì câu trả lời yêu thích của bạn sẽ phụ thuộc vào những công cụ bạn thực sự quan tâm (điều này đưa tôi trở lại thời gian hơn một thập kỷ trước đây), khi trách nhiệm của tôi bao gồm quản lý nhóm. các truy vấn hoạt động tốt trên hơn nửa tá động cơ khác nhau - nói về công việc ác mộng ...! -).

Các vấn đề liên quan