MSSQL

HAVING 절

eloyb 2024. 11. 19. 05:05

SQL에서 Having 절은 SELECT 문에서 집계 함수로 집계된 자료를 다시한번 필터링 하기 위한 용도로 사용됩니다. 데이터 를 필터링 하기 위한 용도는 WHERE 절과 HAVING절이 사용되는 데 WHERE 절은 집계되지 않은 자료에 대한 조건이고 HAVING 절은 집계된 자료에 대한 조건이라고 생각하면 됩니다.

 

HAVING 절의 사용법은 아래와 같습니다.

 

SELECT column, column, column...

FROM table_name

WHERE search_condition GROUP BY column_name(s) HAVING search_condition ORDER BY column_name(s)

그러면 하나씩 예들 들어가면서 알아보도록 하겠습니다.

 

Product 테이블

SELECT ProductName FROM Products WHERE RetailPrice=MAX(RetailPrice) -- 오류 메시지 --집계가 HAVING 절 이나 SELECT 목록에 포함된 하위 쿼리 내에 없으면 --WHERE 절에 나타날 없습니다. 또한 집계 중인 열은 외부 참조입 니다.

위에서 설명했듯이 집계함수를 WHERE 절에서 사용하면 오류가 나면서 쿼리문이 실행되지 않습니다. 그러면 위와 같은 구문은 오류가 나는 걸까요? 단순히 집계함수는 WHERE 절에서 사용할 없다는 것으로 알고 있기 보단 실제 원인이 무엇인지를 알아야 정확한 지식이 되고 실제 현업에서 문제 없이 사용할 수 있는 토대가 될 수 있습니다.

 

그 이유는 집계함수의 용도가 SELECT를 하지 않으면 나올 수 없는 값이기 때문입니다. 집계 함수의 종류들인 SUM, AVG, MAX, MIN 등의 함수를 모두 실제 사용하기 위해서 SELECT 통해서만 사용할 있기 때문에 WHERE 절에 직 접 집계함수를 이용해서 쿼리문을 만들 수 없게 되는 것입니다.

그러면 WHERE 절에서 SELECT를 사용할 수 있다면 WHERE 절 내에서도 집계함수를 사용할 수 있는 것 아닌가? 이렇게 생각했다면 핵심을 제대로 집으신 겁니다. 그렇습니다. WHERE 내에서 서브쿼리를 이용한다면 집계함수를 WHERE 절 안에서 얼마든지 사용할 수 있습니다.

SELECT ProductName FROM Products WHERE RetailPrice =(SELECT MAX(RetailPrice) FROM Products) WHERE 안에 위와 같이 서브쿼리를 이용해서 쿼리문을 작성한다면 아무 문제가 없이 정확히 원하는 데이터가 출력되 게 됩니다.

SELECT Customers.CState AS 지역, SUM(Order_Details.QuantityOrdered * Order_Details.QuotedPrice) AS 주 문합계 FROM (Customers INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID) INNER JOIN Order_Details ON Orders.OrderNumber = Order_Details.OrderNumber GROUP BY Customers.CState HAVING SUM(Order_Details.QuantityOrdered * Order_Details.QuotedPrice) > 5000 AND CState IN ('강남구', '마포구', '용산구')

위의 예제는 강남구, 마포구, 용산구에서 주문 합계가 5000 이 넘는 주문의 합계를 출력하는 쿼리문입니다. SELECT에서 SUM 함수를 통해서 집계한 자료를 바탕으로 HAVING 절을 이용해서 필터링을 해서 원하는 자료를 출력할 수 있습니다.

SELECT Customers.CState AS 지역, SUM(Order_Details.QuantityOrdered * Order_Details.QuotedPrice) AS 주 문합계 FROM (Customers INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID) INNER JOIN Order_Details ON Orders.OrderNumber = Order_Details.OrderNumber WHERE Customers.CState IN ('강남구', '마포구', '용산구') GROUP BY Customers.CState HAVING SUM(Order_Details.QuantityOrdered * Order_Details.QuotedPrice) > 5000

위의 예제를 똑같은 쿼리문을 WHERE 절을 이용해서 만들어 낸 자료입니다.

WHERE 절을 이용해서 먼저 한번 필터링을 거칠 수 있다면 이 방법을 사용하는 것이 더 효율적입니다.

위의 예에서 있듯이 HAVING 절은 SELECT에서 한번 집계한 자료를 가지고 다시 한번 필터링을 하는 사용한다고 생각하면 됩니다.

 

예를 들어 다음과 같은 경우가 있을 수 있습니다.

) 모든 제품들의 평균 매출액보다 매출액을 표시하시오 (AVG HAVING 사용할 있음) ) 양파와 호박을 모두 포함하는 조리법을 출력하시오 (Count HAVING을 사용할 수 있음)

) 지역에서 후원금의 총액이 1억원 이상인 후보의 리스트를 출력하시오 (SUM HAVING을 사용할 수 있음)

 

SELECT Customers.FirstName + ' ' + Customers.LastName AS 성명, Orders.OrderDate,SUM(Order_Details.QuotedPrice * Order_Details.QuantityOrdered) AS 주문금액 FROM (Customers INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID) INNER JOIN Order_Details

 

ON Orders.OrderNumber = Order_Details.OrderNumber GROUP BY Customers.FirstName, Customers.LastName, Orders.OrderDate HAVING SUM(Order_Details.QuotedPrice * Order_Details.QuantityOrdered) > 10000

위의 예제는 고객명과 주문날짜를 출력하면서 고객들이 주문한 금액이 10,000원이 넘는 리스트를 출력하는 예제입니 다.

 

고객과 주문날짜를 같이 출력하도록 했기때문에 고객의 경우라도 날짜별 주문 금액을 계산해서 10,000원이 넘는 리스 트를 출력하게 됩니다. 만약 날짜를 제거한다면 고객별 주문 금액이 출력되게 되므로 각 고객은 한번만 출력될 것입니다..

 

'MSSQL' 카테고리의 다른 글

데이터 그룹화(GROUP BY)  (1) 2024.11.18
집계함수  (0) 2024.11.17
서브쿼리(Sub Query)  (3) 2024.11.16
데이터베이스 조인(UNION)  (2) 2024.11.15
외부조인  (0) 2024.11.14