HAVING
HAVING은 GROUP BY가 처리된 결과에 필터 조건을 추가하기 위해 사용한다.
•
HAVING은 GROUP BY와 ORDER BY 절 사이에 사용
•
SELECT 절과 마찬가지로 HAVING 절에는,
◦
GROUP BY에 사용한 컬럼만 HAVING 절에 그대로 사용할 수 있다.
◦
GROUP BY에 사용하지 않은 컬럼은 반드시 집계함수와 함께 사용해야 한다.
-- [SQL-5-4-1]
-- 22년1월1일~22년1월2일 주문 데이터를 ShopId 별로 GROUP BY
-- ShopId별 주문 건수(COUNT(*))가 5건 이상인 데이터만 조회(HAVING 처리)
SELECT T1.ShopId
,SUM(T1.OrdAmt) OrdAmt ,COUNT(*) OrdCnt
FROM startdb.Ord T1
WHERE T1.OrdDtm >= STR_TO_DATE('20220101','%Y%m%d')
AND T1.OrdDtm < STR_TO_DATE('20220103','%Y%m%d')
GROUP BY T1.ShopId
HAVING COUNT(*) >= 5
ORDER BY OrdCnt DESC;
ShopId OrdAmt OrdCnt
------ ---------- ------
S001 115500.000 19
S003 28500.000 5
-- [SQL-5-4-2]
-- GROUP BY에 없는 OrdSt 컬럼을 집계함수 없이 사용했으므로 오류
-- OrdSt 조건은 WHERE 절에서 사용하거나, 집계함수 처리해서 사용해야 한다.
SELECT T1.ShopId
,SUM(T1.OrdAmt) OrdAmt ,COUNT(*) OrdCnt
FROM startdb.Ord T1
WHERE T1.OrdDtm >= STR_TO_DATE('20220101','%Y%m%d')
AND T1.OrdDtm < STR_TO_DATE('20220103','%Y%m%d')
GROUP BY T1.ShopId
HAVING T1.OrdSt = 'PKUP' -- > 잘못된 사용
ORDER BY OrdCnt DESC;
-- [SQL-5-4-3]
-- HAVING 조건도 여러개 조합이 가능
SELECT T1.ShopId
,SUM(T1.OrdAmt) OrdAmt ,COUNT(*) OrdCnt
FROM startdb.Ord T1
WHERE T1.OrdDtm >= STR_TO_DATE('20220101','%Y%m%d')
AND T1.OrdDtm < STR_TO_DATE('20220103','%Y%m%d')
GROUP BY T1.ShopId
HAVING (COUNT(*) >= 5 OR SUM(T1.OrdAmt) >= 20000)
ORDER BY OrdCnt DESC;
-- [SQL-5-4-4]
SELECT T1.ShopId
,SUM(T1.OrdAmt) OrdAmt ,COUNT(*) OrdCnt
FROM startdb.Ord T1
WHERE T1.OrdDtm >= STR_TO_DATE('20220101','%Y%m%d')
AND T1.OrdDtm < STR_TO_DATE('20220103','%Y%m%d')
GROUP BY T1.ShopId
HAVING COUNT(*) >= 5 AND SUM(T1.OrdAmt) >= 50000
ORDER BY OrdCnt DESC;
SQL
복사
WHERE 절을 거쳐 GROUP BY를 거쳐, HAVING을 거쳐 데이터 집합이 어떻게 변하는지 그려보면 다음과 같습니다.
BOOSTER QUIZ
BOOSTER QUIZ ERD
BOOSTER QUIZ 5-4-1
아래는 상품카테고리(ItemCat)로 GROUP BY 처리하는 SQL이며 에러가 발생하고 있다. GROUP BY를 유지할 경우, 아래 SQL에서 잘못된 부분 두 곳을 찾으시오.
SELECT T1.ItemCat -- 1
,COUNT(*) ItemCnt -- 2
,T1.ItemSizeCd -- 3
FROM startdb.Item T1
WHERE T1.HotColdCd = 'HOT'
GROUP BY T1.ItemCat -- 4
HAVING COUNT(*) >= 2 -- 5
AND
T1.ItemId NOT LIKE 'A%' -- 6
;
SQL
복사