GROUP BY
GROUP BY는 데이터를 그룹화하기 위해 사용한다. 그룹화란 같은 값을 가진 데이터를 모으는 것을 뜻한다. 데이터를 그룹화하면 같은 값을 가진 데이터끼리 모여 하나의 그룹이 만들어진다. 만들어진 그룹은 DB 내부적으로만 가지고 있으며, 그룹화된 데이터를 출력하게 되면 그룹별로 한 건의 레코드만 출력을 할 수 있다.
아래는 상품(Item) 테이블에서 상품사이즈코드(ItemSizeCd)가 REG(Regular)이면서 출시일자(LaunchDt)가 2019년 1월 1일인 데이터를 조회하는 SQL이다.
-- [SQL-5-1-1] Item 데이터 조회
SELECT T1.ItemId ,T1.ItemNm ,T1.ItemCat ,T1.HotColdCd
FROM startdb.Item T1
WHERE T1.ItemSizeCd = 'REG'
AND T1.LaunchDt = STR_TO_DATE('20190101','%Y%m%d')
ORDER BY T1.ItemCat;
-- 결과
ItemId ItemNm ItemCat HotColdCd
------ ------------------- ------- ---------
HCHR Hot Chocolate(R) BEV HOT
LEMR Lemonade(R) BEV COLD
BGLR Bagel(R) BKR HOT
BMFR Blueberry Muffin(R) BKR COLD
CMFR Chocolate Muffin(R) BKR COLD
AMR Americano(R) COF HOT
CLR Cafe Latte(R) COF HOT
IAMR Iced Americano(R) COF COLD
ICLR Iced Cafe Latte(R) COF COLD
SQL
복사
위 SQL의 결과 중에 상품카테고리(ItemCat) 데이터를 살펴보자. BEV(음료) 상품이 두 건이 이고, BKR(베이커리) 상품이 세 건, COF(커피)인 데이터가 네 건이 있다. 이러한 결과 데이터를 상품카테고리(ItemCat)별로 그룹을 만들어 보려고 한다. 다시 말해, COF인 데이터를 모아서 하나의 그룹을 만들고, BKR인 데이터로 하나의 그룹, BEV인 데이터로 하나의 그룹을 만드는 것이다. 이를 위해 GROUP BY를 사용할 수 있다. 아래와 같이 위의 SQL을 변경하자.
•
ORDER BY 전에 GROUP BY T1.ItemCat를 추가
•
SELECT 절에는 T1.ItemCat 컬럼만 사용
-- [SQL-5-1-2] [SQL-5-1-1]을 ItemCat로 GROUP BY 처리
SELECT T1.ItemCat -- >
FROM startdb.Item T1
WHERE T1.ItemSizeCd = 'REG'
AND T1.LaunchDt = STR_TO_DATE('20190101','%Y%m%d')
GROUP BY T1.ItemCat -- >
ORDER BY T1.ItemCat;
ItemCat
-------
BEV
BKR
COF
SQL
복사
위와 같이 GROUP BY를 사용하면, GROUP BY에 정의된 컬럼의 값이 같은 데이터끼리 모여 그룹이 만들어진다.
•
ItemCat가 BEV인 두 건의 데이터가 모여 하나의 그룹이 만들어진다.
•
ItemCat가 BKR인 세 건의 데이터가 모여 하나의 그룹이 만들어진다.
•
ItemCat가 COF인 네 건의 데이터가 모여 하나의 그룹이 만들어진다.
SQL에 GROUP BY가 사용되면, SELECT 절과 ORDER BY 절에는 GROUP BY에 사용한 컬럼만 사용할 수 있다. 나머지 컬럼은 집계함수 처리를 해야만 사용할 수 있다. 우선은 이 부분을 공식처럼 외우기 바란다. GROUP BY에 ItemCat를 사용했으므로 SELECT 절에도 ItemCat만 사용할 수 있으며 결과적으로 BEV, BKR, COF 세 건의 데이터만 출력된다. 그룹으로 만들어진 데이터는 그룹별로 한 건의 레코드만 결과로 보여줄 수 있다는 점을 기억하기 바란다.
이번에는 원래의 SQL을 Hot/Cold구분코드(HotColdCd) 별로 GROUP BY 처리를 해보자. 원래의 SQL을 기준으로 아래와 같이 변경합니다.
•
GROUP BY T1.HotColdCd를 추가.
•
SELECT 절에는 T1.HotColdCd 컬럼만 사용
•
ORDER BY 도 T1.HotColdCd로 변경.
-- [SQL-5-1-3] [SQL-5-1-1]을 HotColdCd로 GROUP BY 처리
SELECT T1.HotColdCd -- >
FROM startdb.Item T1
WHERE T1.ItemSizeCd = 'REG'
AND T1.LaunchDt = STR_TO_DATE('20190101','%Y%m%d')
GROUP BY T1.HotColdCd -- >
ORDER BY T1.HotColdCd -- >
;
HotColdCd
---------
COLD
HOT
SQL
복사
GROUP BY는 결과적으로 데이터를 압축하는 효과가 있다. 아래 그림을 통해 SQL의 각 구문에 따라 테이블의 데이터가 어떻게 변해가는지 살펴보기 바랍니다.
위 그림을 좀 더 간략화해보면 다음과 같다. WHERE 절과 GROUP BY 절을 사용하면서 이와 같이 데이터 집합이 변형되는 것을 항상 머릿속에 떠올리기 바란다. 나중에 복잡한 데이터 집합을 다룰 때 도움이 된.
BOOSTER QUIZ
BOOSTER QUIZ ERD
BOOSTER QUIZ 5-1-1
(SQL-1)과 (결과-1)을 참고해, (SQL-2)를 실행하면 나올 (결과-2)를 채우시오.
•
SQL을 실행하지 않고 (결과-2)를 예측해서 채우시오.
•
(SQL-2)는 (SQL-1)을 GROUP BY 처리한 SQL이다.
-- (SQL-1)
SELECT T1.OrdNo, T1.OrdDtm ,T1.ShopId ,T1.OrdSt
FROM startdb.Ord T1
WHERE T1.OrdNo IN (91946,91917,91916,91872,91763)
ORDER BY T1.OrdNo DESC;
-- (결과-1)
OrdNo OrdDtm ShopId OrdSt
----- ------------------- ------ -----
91946 2023-03-31 20:30:00 S200 PREF
91917 2023-03-31 20:00:00 S131 MFGC
91916 2023-03-31 20:00:00 S111 MFGC
91872 2023-03-31 19:00:00 S107 PKUP
91763 2023-03-31 18:00:00 S107 PKUP
SQL
복사
-- (SQL-2)
SELECT T1.OrdSt
FROM startdb.Ord T1
WHERE T1.OrdNo IN (91946,91917,91916,91872,91763)
GROUP BY T1.OrdSt
ORDER BY T1.OrdSt ASC;
-- (결과-2)
SQL
복사
BOOSTER QUIZ 5-1-2
(SQL-1)과 (결과-1)을 참고해, (SQL-2)를 실행하면 나올 (결과-2)를 채우시오.
•
SQL을 실행하지 않고 (결과-2)를 예측해서 채우시오.
•
(SQL-2)는 (SQL-1)을 GROUP BY 처리한 SQL이다.
-- (SQL-1)
SELECT T1.OrdNo, T1.OrdDtm ,T1.ShopId ,T1.OrdSt
FROM startdb.Ord T1
WHERE T1.OrdNo IN (91946,91917,91916,91872,91763)
ORDER BY T1.OrdNo DESC;
-- (결과-1)
OrdNo OrdDtm ShopId OrdSt
----- ------------------- ------ -----
91946 2023-03-31 20:30:00 S200 PREF
91917 2023-03-31 20:00:00 S131 MFGC
91916 2023-03-31 20:00:00 S111 MFGC
91872 2023-03-31 19:00:00 S107 PKUP
91763 2023-03-31 18:00:00 S107 PKUP
SQL
복사
-- (SQL-2)
SELECT T1.ShopId
FROM startdb.Ord T1
WHERE T1.OrdNo IN (91946,91917,91916,91872,91763)
GROUP BY T1.ShopId
ORDER BY T1.ShopId;
-- (결과-2)
SQL
복사