2012-02-12 24 views
127

Tôi có hai bảng:SQL - có VS nơi

1. Lecturers (LectID, Fname, Lname, degree). 
2. Lecturers_Specialization (LectID, Expertise). 

Tôi muốn tìm các giảng viên với Chuyên ngành nhất. Khi tôi cố gắng này, nó không hoạt động:

SELECT 
    L.LectID, 
    Fname, 
    Lname 
FROM Lecturers L, 
    Lecturers_Specialization S 
WHERE L.LectID = S.LectID 
AND COUNT(S.Expertise) >= ALL (SELECT 
    COUNT(Expertise) 
FROM Lecturers_Specialization 
GROUP BY LectID); 

Nhưng khi tôi cố gắng này, nó hoạt động:

SELECT 
    L.LectID, 
    Fname, 
    Lname 
FROM Lecturers L, 
    Lecturers_Specialization S 
WHERE L.LectID = S.LectID 
GROUP BY L.LectID, 
     Fname, 
     Lname 
HAVING COUNT(S.Expertise) >= ALL (SELECT 
    COUNT(Expertise) 
FROM Lecturers_Specialization 
GROUP BY LectID); 

lý do là gì? Cảm ơn.

+2

Bạn có thể làm rõ phiên bản SQL nào bạn đang sử dụng (MySQL, MS SQL, PostgreSQL, Oracle, v.v.). Ngoài ra, khi bạn nói "không hoạt động", bạn có nghĩa là kết quả không như bạn mong đợi hoặc có lỗi biên dịch/phân tích cú pháp không? – jklemmack

+1

Tại sao bạn sử dụng TẤT CẢ thay vì MAX ?. Có lợi thế nào không? – skan

Trả lời

237

WHERE giới thiệu điều kiện trên các hàng riêng lẻ; Mệnh đề HAVING giới thiệu một điều kiện trên tập hợp, tức là kết quả lựa chọn trong đó một kết quả, chẳng hạn như số lượng, trung bình, phút, tối đa hoặc tổng, được tạo từ nhiều hàng. Truy vấn của bạn yêu cầu loại điều kiện thứ hai (tức là điều kiện trên tổng hợp) do đó HAVING hoạt động chính xác.

Theo quy tắc chung, hãy sử dụng WHERE trước GROUP BYHAVING sau GROUP BY. Nó là một nguyên tắc khá nguyên thủy, nhưng nó hữu ích trong hơn 90% các trường hợp.

Trong khi bạn đang ở đó, bạn có thể muốn viết lại truy vấn của bạn sử dụng phiên bản ANSI của tham gia:

SELECT L.LectID, Fname, Lname 
FROM Lecturers L 
JOIN Lecturers_Specialization S ON L.LectID=S.LectID 
GROUP BY L.LectID, Fname, Lname 
HAVING COUNT(S.Expertise)>=ALL 
(SELECT COUNT(Expertise) FROM Lecturers_Specialization GROUP BY LectID) 

này sẽ loại bỏ WHERE đã được sử dụng như một theta điều kiện join.

31

HAVING hoạt động trên tổng hợp. Vì COUNT là một hàm tổng hợp, bạn không thể sử dụng nó trong mệnh đề WHERE.

Here's một số đọc từ MSDN trên các hàm tổng hợp. Điều khoản

8

Bạn không thể sử dụng mệnh đề where với hàm tổng hợp vì nơi tìm nạp bản ghi trên cơ sở điều kiện, nó đi vào bản ghi bảng theo bản ghi và sau đó tìm nạp bản ghi trên cơ sở điều kiện chúng tôi cung cấp. Vì vậy, thời gian đó chúng tôi không thể ở đâu khoản. Trong khi có điều khoản hoạt động trên resultsSet mà cuối cùng chúng tôi nhận được sau khi chạy một truy vấn.

Ví dụ truy vấn:

select empName, sum(Bonus) 
from employees 
order by empName 
having sum(Bonus) > 5000; 

này sẽ lưu trữ các ResultSet trong một bộ nhớ tạm thời, sau đó có điều khoản sẽ thực hiện công việc của mình. Vì vậy, chúng ta có thể dễ dàng sử dụng các hàm tổng hợp ở đây.

+1

Tôi nghĩ chúng ta không thể sử dụng mệnh đề HAVING mà không có mệnh đề GROUP BY. Vị trí của HAVING khoản - CHỌN -> FROM -> WHERE -> GROUP BY -> HAVING -> ORDER BY – Ronnie

8
  1. Điều khoản WHERE có thể được sử dụng với câu lệnh SELECT, INSERT và UPDATE, trong khi chỉ có thể sử dụng HAVING với câu lệnh SELECT.

  2. WHERE lọc hàng trước khi tổng hợp (GROUP BY), trong khi HAVING nhóm bộ lọc sau khi tổng hợp được thực hiện.

  3. Hàm tổng hợp không thể được sử dụng trong mệnh đề WHERE trừ khi nó nằm trong truy vấn con chứa trong mệnh đề HAVING, trong khi hàm tổng hợp có thể được sử dụng trong mệnh đề HAVING.

Source

2

1. Chúng ta có thể sử dụng chức năng tổng hợp với HAVING khoản không phải bằng mệnh đề WHERE ví dụ tối thiểu, tối đa, trung bình

2. mệnh đề WHERE loại bỏ các tuple kỷ lục bởi tuple mệnh đề HAVING loại bỏ toàn bộ nhóm từ bộ sưu tập của nhóm

Chủ yếu là HAVING được sử dụng khi bạn có các nhóm dữ liệu và WHERE được sử dụng khi bạn có dữ liệu trong hàng .

4

Không thấy ví dụ về cả hai trong một truy vấn. Vì vậy, ví dụ này có thể hữu ích.

/** 
INTERNATIONAL_ORDERS - table of orders by company by location by day 
companyId, country, city, total, date 
**/ 

SELECT country, city, sum(total) totalCityOrders 
FROM INTERNATIONAL_ORDERS with (nolock) 
WHERE companyId = 884501253109 
GROUP BY country, city 
HAVING country = 'MX' 
ORDER BY sum(total) DESC 

Điều này lọc bảng đầu tiên theo công tyId, sau đó nhóm bảng đó (theo quốc gia và thành phố) và bổ sung lọc thành tập hợp thành phố Mexico. CompanyId không cần thiết trong tập hợp nhưng chúng tôi có thể sử dụng WHERE để lọc ra chỉ những hàng chúng tôi muốn trước khi sử dụng GROUP BY.

6

Trước tiên, chúng ta nên biết thứ tự thực hiện các khoản là FROM> WHERE> GROUP BY> HAVING> DISTINCT> CHỌN> ĐẶT HÀNG. Kể từ ĐÂU khoản được thực hiện trước khi GROUP BY khoản các hồ sơ không thể được lọc bằng cách áp dụng ĐÂU đến một GROUP THEO áp dụng hồ sơ.

"HAVING giống với mệnh đề WHERE nhưng được áp dụng trên các bản ghi được nhóm".

đầu tiên ĐÂU khoản fetches các hồ sơ dựa trên điều kiện thì GROUP BY nhóm khoản chúng cho phù hợp và sau đó mệnh đề HAVING fetches các hồ sơ nhóm dựa trên việc có điều kiện.

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