Search

5-5. GROUP BY 컬럼의 변형

GROUP BY 컬럼의 변형

GROUP BY 컬럼을 변형해서 처리할 수 있다.
-- [SQL-5-5-1] GROUP BY 처리전 SQL -- ItemNm의 뒤의 세 글자를 ItemSizeNm으로 표시합니다. SELECT T1.ItemId ,T1.ItemNm ,SUBSTR(T1.ItemNm,-3) ItemSizeNm FROM startdb.Item T1 WHERE T1.ItemCat = 'COF' AND T1.LaunchDt = STR_TO_DATE('20190101','%Y%m%d') ORDER BY T1.ItemId; -- GROUP BY 처리전 결과 ItemId ItemNm ItemSizeNm ------ ------------------ ---------- AMB Americano(B) (B) AMR Americano(R) (R) CLB Cafe Latte(B) (B) CLR Cafe Latte(R) (R) IAMB Iced Americano(B) (B) IAMR Iced Americano(R) (R) ICLB Iced Cafe Latte(B) (B) ICLR Iced Cafe Latte(R) (R) -- [SQL-5-5-2] SUBSTR(T1.ItemNm,-3)으로 GROUP BY 처리후 SELECT SUBSTR(T1.ItemNm,-3) ItemSizeNm ,COUNT(*) ItemCnt FROM startdb.Item T1 WHERE T1.ItemCat = 'COF' AND T1.LaunchDt = STR_TO_DATE('20190101','%Y%m%d') GROUP BY SUBSTR(T1.ItemNm,-3) ORDER BY ItemCnt DESC; -- GROUP BY 처리후 결과 ItemSizeNm ItemCnt ---------- ------- (B) 4 (R) 4
SQL
복사
아래는 OrdDtm(주문일시) 값에 DATE_FORMAT을 사용해 년월 형태의 문자로 변환해 GROUP BY 처리하는 SQL입니다. 이처럼 일자 데이터를 년월로 변형해 데이터를 집계하는 패턴은 매우 자주 사용된다.
-- [SQL-5-5-3] GROUP BY 처리전 SQL(OrdDtm을 OrdYm으로 변환) SELECT T1.OrdNo, T1.OrdDtm ,T1.OrdAmt ,DATE_FORMAT(T1.OrdDtm,'%Y%m') OrdYm FROM startdb.Ord T1 WHERE T1.OrdDtm >= STR_TO_DATE('20221001','%Y%m%d') AND T1.OrdDtm < STR_TO_DATE('20230101','%Y%m%d') AND T1.ShopId = 'S263' ORDER BY T1.OrdNo; -- GROUP BY 처리전 결과 OrdNo OrdDtm OrdAmt OrdYm ----- ------------------- -------- ------ 42456 2022-10-02 13:00:00 4000.000 202210 45886 2022-10-30 13:00:00 4000.000 202210 46204 2022-11-02 13:00:00 4500.000 202211 49621 2022-11-30 13:00:00 8500.000 202211 51228 2022-12-02 13:00:00 2500.000 202212 55909 2022-12-22 13:00:00 4000.000 202212 63040 2022-12-25 13:00:00 8500.000 202212 66019 2022-12-30 13:00:00 4000.000 202212 -- [SQL-5-5-4] -- GROUP BY 처리후 SQL -- 주문년월(OrdYm)별 주문 데이터를 집계합니다. SELECT DATE_FORMAT(T1.OrdDtm,'%Y%m') OrdYm ,COUNT(*) OrdCnt ,SUM(T1.OrdAmt) OrdAmt FROM startdb.Ord T1 WHERE T1.OrdDtm >= STR_TO_DATE('20221001','%Y%m%d') AND T1.OrdDtm < STR_TO_DATE('20230101','%Y%m%d') AND T1.ShopId = 'S263' GROUP BY DATE_FORMAT(T1.OrdDtm,'%Y%m') ORDER BY DATE_FORMAT(T1.OrdDtm,'%Y%m'); OrdYm OrdCnt OrdAmt ------ ------ --------- 202210 2 8000.000 202211 2 13000.000 202212 4 19000.000
SQL
복사
컬럼 간의 계산 결과를 GROUP BY에 사용할 수도 있다. 아래는 주문일시부터 제조완료까지 몇 분이 걸렸는지 계산해 GROUP BY 항목으로 사용하는 SQL이다.
CompMin(제조완료분수)
TIMESTAMPDIFF를 사용해 주문일시(OrdDtm)부터 제조완료(PrepareCmpDtm)까지 몇 분이 걸렸는지 계산한 값.
-- [SQL-5-5-5] -- GROUP BY 처리전 SQL -- CompMin: TIMESTAMPDIFF를 사용해 주문일시부터 제조완료까지 몇 분이 걸렸는지 계산 SELECT T1.OrdNo, T1.OrdDtm ,T1.PrepareCmpDtm ,TIMESTAMPDIFF(MINUTE,T1.OrdDtm,T1.PrepareCmpDtm) CompMin FROM startdb.Ord T1 WHERE T1.OrdDtm >= STR_TO_DATE('20221224','%Y%m%d') AND T1.OrdDtm < STR_TO_DATE('20221225','%Y%m%d') ORDER BY CompMin ASC; OrdNo OrdDtm PrepareCmpDtm CompMin ----- ------------------- ------------------- ------- 59830 2022-12-24 07:30:00 2022-12-24 07:32:00 2 59865 2022-12-24 08:00:00 2022-12-24 08:02:00 2 59978 2022-12-24 09:00:00 2022-12-24 09:02:00 2 60008 2022-12-24 09:00:00 2022-12-24 09:02:00 2 60060 2022-12-24 10:00:00 2022-12-24 10:02:00 2 ... 생략 ... -- [SQL-5-5-6] -- GROUP BY 처리된 SQL SELECT TIMESTAMPDIFF(MINUTE,T1.OrdDtm,T1. PrepareCmpDtm) CompMin ,COUNT(*) OrdCnt FROM startdb.Ord T1 WHERE T1.OrdDtm >= STR_TO_DATE('20221224','%Y%m%d') AND T1.OrdDtm < STR_TO_DATE('20221225','%Y%m%d') GROUP BY TIMESTAMPDIFF(MINUTE,T1.OrdDtm,T1. PrepareCmpDtm) ORDER BY TIMESTAMPDIFF(MINUTE,T1.OrdDtm,T1. PrepareCmpDtm); -- GROUP BY 처리후 결과 CompMin OrdCnt ------- ------ 2 24 3 99 4 122 5 149 6 141 7 147 8 172 9 139 10 173 11 221 12 192 13 144 14 112 15 87 16 87 17 58 18 56 19 57 20 32
SQL
복사
이와 같이 시간을 계산하고, 계산된 시간 기준으로 데이터를 집계하는 것은 중요한 분석 포인트 중 하나다. 위 결과를 시각화 해보면 다음과 같다. 시각화를 통해 주문을 처리하는 시간이 8분에서 12분 사이에 집중되어 있는 것을 알 수 있다. 이를 통해 제조 완료 시간 단축이 필요한지, 지금도 괜찮은지에 대해 회의를 해볼 수 있을 것이다.
이처럼 계산 결과 값을 그룹핑하는 패턴은 새로운 관점으로 데이터를 분석하게 해준다. 많은 사람들이 GROUP BY를 사용할 줄 알지만, 데이터 분석을 위해 특정 값이 계산된 내용을 GROUP BY에 사용하는 것은 잘 모른다. 이처럼 분석해볼 수 있다는 것도 잘 떠올리지 못한다. GROUP BY에 계산된 결과를 사용할 수 있다는 점을 꼭 기억하기 바란다.

별칭 처리 주의 사항

GROUP BY에서는 컬럼의 별칭을 사용할 수 없다.
하지만 MySQL은 버전이나 설정에 따라 가능(권장하지 않는다.), 오라클은 불가능
GROUP BY에서 컬럼의 별칭을 정의할 수 없다.
ORDER BY와 마찬가지로 컬럼의 별칭 정의는 SELECT 절에서만 가능하다.
-- [SQL-5-5-7] -- GROUP BY에 별칭을 사용, 권장하지 않음 SELECT DATE_FORMAT(T1.OrdDtm,'%Y%m') OrdYm ,COUNT(*) OrdCnt FROM startdb.Ord T1 WHERE T1.OrdDtm >= STR_TO_DATE('20221001','%Y%m%d') AND T1.OrdDtm < STR_TO_DATE('20221231','%Y%m%d') AND T1.ShopId = 'S263' GROUP BY OrdYm -- > 권장하지 않음! ORDER BY OrdYm; -- [SQL-5-5-8] -- GROUP BY에 원래 컬럼을 사용, 권장 SELECT DATE_FORMAT(T1.OrdDtm,'%Y%m') OrdYm ,COUNT(*) OrdCnt FROM startdb.Ord T1 WHERE T1.OrdDtm >= STR_TO_DATE('20221001','%Y%m%d') AND T1.OrdDtm < STR_TO_DATE('20221231','%Y%m%d') AND T1.ShopId = 'S263' GROUP BY DATE_FORMAT(T1.OrdDtm,'%Y%m') -- > 권장 ORDER BY OrdYm; -- [SQL-5-5-9] -- GROUP BY 에서 컬럼 별칭을 정의할 수 없다. -- ORDER BY도 마찬가지다. SELECT DATE_FORMAT(T1.OrdDtm,'%Y%m') OrdYm ,COUNT(*) OrdCnt FROM startdb.Ord T1 WHERE T1.OrdDtm >= STR_TO_DATE('20221001','%Y%m%d') AND T1.OrdDtm < STR_TO_DATE('20221231','%Y%m%d') AND T1.ShopId = 'S263' GROUP BY DATE_FORMAT(T1.OrdDtm,'%Y%m') OrdYm -- > 별칭으로 오류 ORDER BY OrdYm;
SQL
복사

BOOSTER QUIZ

BOOSTER QUIZ ERD

BOOSTER QUIZ 5-5-1

(SQL-1)과 (결과-1)을 참고해, (SQL-2)를 실행하면 나올 (결과-2)를 채우시오.
SQL을 실행하지 않고 (결과-2)를 예측해서 채우시오.
(SQL-2)는 (SQL-1)을 GROUP BY 처리한 SQL이다.
-- (SQL-1) SELECT T1.OrdNo ,T1.OrdDtm FROM startdb.Ord T1 WHERE T1.ShopId = 'S092' AND T1.OrdDtm>=STR_TO_DATE('20210901','%Y%m%d') AND T1.OrdDtm< STR_TO_DATE('20211101','%Y%m%d') ORDER BY T1.OrdNo ASC; -- (결과-1) OrdNo OrdDtm ----- ------------------- 16617 2021-09-04 13:30:00 16831 2021-09-06 13:30:00 16896 2021-09-08 13:30:00 17119 2021-09-13 13:30:00 17202 2021-09-21 13:30:00 17776 2021-10-04 13:30:00 17990 2021-10-06 13:30:00
SQL
복사
-- (SQL-2) SELECT DATE_FORMAT(T1.OrdDtm,'%Y%m') YM ,COUNT(*) CNT FROM startdb.Ord T1 WHERE T1.ShopId = 'S092' AND T1.OrdDtm>=STR_TO_DATE('20210901','%Y%m%d') AND T1.OrdDtm< STR_TO_DATE('20211101','%Y%m%d') GROUP BY DATE_FORMAT(T1.OrdDtm,'%Y%m') ORDER BY YM ASC; -- (결과-2)
SQL
복사

BOOSTER QUIZ 5-5-2

S019 매장의 2022년 주문 데이터를 주문년월별로 주문 건수와 주문금액 합계를 구해주세요.
대상 테이블: 주문(Ord)
조회 조건: ShopId가 S019 이면서 OrdDtm이 2022년인 주문 데이터
조회 컬럼: OrdYm, OrdCnt ,OrdAmtSum
추가 조건
OrdYm은 OrdDtm을 년월(YYYYMM) 형태의 문자로 변형한 항목
OrdYm 별로 GROUP BY 처리하시오.
OrdCnt는 OrdYm 별 데이터 건수
OrdAmt는 OrdYm 별 OrdAmt를 SUM 집계한 값
정렬 기준: OrdYm으로 내림차순 정렬하시오.
OrdYm OrdCnt OrdAmtSum ------ ------ ---------- 202012 25 136500.000 202011 8 35000.000 202010 8 57000.000 … 생략 …
SQL
복사

BOOSTER QUIZ 5-5-3

2020년 주문에 대해, 주문 시간대별로 주문 건수를 알고 싶어, 가장 주문 건수가 많은 시간대를 확인하려고요.
대상 테이블: 주문(Ord)
조회 조건: OrdDtm이 2020년인 주문 데이터
조회 컬럼: OrdHour, OrdCnt
추가 조건
OrdHour는 OrdDtm에서 DATE_FORMAT을 사용해 시간(%H)만 추출한 항목
OrdHour 별로 GROUP BY 처리하시오.
OrdCnt는 OrdHour 별 데이터 건수
정렬 기준: OrdCnt로 내림차순 정렬하시오.
OrdHour OrdCnt ------- ------ 14 1886 13 1348 11 1305 12 1242 … 생략 …
SQL
복사
Upper: 5. GROUP BY