SQL-VS 사용


202

다음 두 테이블이 있습니다.

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

가장 전문화 된 강사를 찾고 싶습니다. 이것을 시도하면 작동하지 않습니다.

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);

그러나 이것을 시도하면 작동합니다.

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); 

이유가 무엇입니까? 감사.


2
사용중인 SQL 버전 (MySQL, MS SQL, PostgreSQL, Oracle 등)을 확인할 수 있습니다. 또한 "작동하지 않습니다"라고 말하면 결과가 예상과 다르거 나 컴파일 / 파싱 오류가있는 것입니까?
jklemmack

2
왜 MAX 대신 ALL을 사용합니까? 어떤 장점이 있습니까?
skan

답변:


351

WHERE절은 개별 행에 조건을 도입합니다 . HAVING절은 집계 에 대한 조건 , 즉 count, average, min, max 또는 sum과 같은 단일 결과가 여러 행 에서 생성 된 선택 결과를 소개합니다 . 쿼리는 두 번째 종류의 조건 (즉, 집계 조건)을 요구하므로 HAVING올바르게 작동합니다.

엄지 손가락, 사용 원칙적으로 WHERE이전 GROUP BYHAVING이후 GROUP BY. 다소 원시적 인 규칙이지만 90 % 이상의 경우에 유용합니다.

이 작업을 수행하는 동안 ANSI 버전의 조인을 사용하여 쿼리를 다시 작성할 수 있습니다.

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)

이것은 세타 조인 조건WHERE 으로 사용 된 것을 제거 할 것 입니다.


39

HAVING집계에서 작동합니다. COUNT집계 함수 이므로 WHERE절 에서 사용할 수 없습니다 .

다음 은 집계 함수에 대한 MSDN 일부 내용입니다.


30

먼저 FROM> WHERE> GROUP BY> HAVING> DISTINCT> SELECT> ORDER BY 절의 실행 순서를 알아야합니다 . 때문에 WHERE 절은 전에 실행됩니다 GROUP BY의 제 기록을 적용하여 필터링 할 수없는 WHERE A를 GROUP BY는 기록을 적용했다.

"HAVING은 WHERE 절과 동일하지만 그룹화 된 레코드에 적용됩니다."

먼저 WHERE 절은 조건에 따라 레코드를 페치 한 다음 GROUP BY 절은 그에 따라 그룹화 한 다음 HAVING 절은 보유 조건에 따라 그룹 레코드를 페치합니다.


이 순서는 항상 사용됩니까? 쿼리 최적화 프로그램에서 순서를 변경하면 어떻게됩니까?
MSIS

1
쿼리 최적화 순서를 변경 @MSIS 경우에도 결과는 동일해야 하는 경우 등 이 순서가 이어졌습니다. 논리적 순서입니다.
Stephen

18
  1. WHERE 절은 SELECT, INSERT 및 UPDATE 문과 함께 사용할 수있는 반면 HAVING은 SELECT 문과 함께 만 사용할 수 있습니다.

  2. WHERE는 집계 전 행 (GROUP BY)을 필터링하는 반면 집계 후 HAVING 필터 그룹은 필터링됩니다.

  3. 집계 함수는 HAVING 절에 포함 된 서브 쿼리에 있지 않으면 WHERE 절에서 사용할 수 없지만 집계 함수는 HAVING 절에서 사용될 수 있습니다.

출처


11

하나의 쿼리에서 둘 다의 예를 보지 못했습니다. 따라서이 예가 도움이 될 수 있습니다.

  /**
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

이를 통해 companyId별로 먼저 테이블을 필터링 한 다음 국가 및 도시별로 그룹화하고 멕시코의 도시 집계로 필터링합니다. companyId는 집계에 필요하지 않았지만 WHERE를 사용하여 GROUP BY를 사용하기 전에 원하는 행만 필터링 할 수있었습니다.


`WHERE companyId = 884501253109 GROUP BY 국가, 도시 HAVING country = 'MX'`~ : WHERE companyId = 884501253109, 국가 = 'MX'GROUP BY 도시`
Etienne Herlaut

[country] 필터링을 WHERE로 옮기는 것만으로 제안한 경우 [country]가 더 이상 GROUP BY 집계에 포함되지 않으므로 SELECT [country]에서 쿼리 오류가 발생하므로 선택할 수 없습니다.
Nhan

최적화는 요컨대 [국가]를 WHERE (으)로 옮기면 나중에 더 작은 데이터가 GROUP BY로 설정되므로 더 중요합니다. 물론 이것은 가능한 용도를 설명하기위한 예일뿐입니다. HAVING sum (total)> 1000으로 변경할 수 있으며 WHERE 및 HAVING을 포함하는 완전히 유효한 경우입니다.
Nhan

9

조건을 기준으로 레코드를 가져 오는 경우 레코드별로 테이블 레코드로 이동 한 다음 제공된 조건을 기반으로 레코드를 가져 오기 때문에 집계 함수와 함께 where 절을 사용할 수 없습니다. 그래서 우리는 where 절을 사용할 수 없습니다. 결과 절에서 절이 작동하는 동안 쿼리를 실행 한 후에 최종적으로 얻을 수 있습니다.

쿼리 예 :

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

그러면 resultSet이 임시 메모리에 저장되고 having 절이 작업을 수행합니다. 여기서 집계 함수를 쉽게 사용할 수 있습니다.


2
GROUP BY 절이 없으면 HAVING 절을 사용할 수 없다고 생각합니다. HAVING 조항의 위치-SELECT-> FROM-> WHERE-> Group
By-

4

1. WHERE 절이 아닌 HAVING 절과 함께 집계 함수를 사용할 수 있습니다 (예 : min, max, avg).

2. WHERE 절은 튜플에 의한 레코드 튜플을 제거합니다. HAVING 절은 그룹 콜렉션에서 전체 그룹을 제거합니다.

대부분 HAVING은 데이터 그룹이있을 때 사용되며 WHERE는 행에 데이터가있을 때 사용됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.