GROUP BY와 UNIQUE KEY
UK(UNIQUE KEY)는 데이터 집합에서 레코드 한 건을 유일하게 식별해낼 수 있는 속성이다. 테이블에 담긴 데이터에는 PK(PRIMARY KEY)가 레코드를 식별하는 UK 역할을 대표로 수행한다. 테이블이 아닌 우리가 SQL로 얻은 결과 데이터 집합에도 마찬가지로 데이터를 식별하는 UK가 있다.
아래 SQL을 살펴보자. Item 테이블에서 ItemCat가 COF인 데이터만 조회하고 있다. 아래 SQL로 얻은 결과집합의 UK는 Itemid다. ItemId는 중복되지 않으며, ItemId로 레코드 한 건을 정확히 골라낼 수 있기 때문이다. 이처럼 테이블에서 데이터를 조회한 후에 데이터가 늘어나거나 그룹화되지 않았다면 테이블의 원래 PK 컬럼을 결과 집합의 UK로 여전히 사용할 수 있다.
-- [SQL-5-9-1]
SELECT T1.ItemId ,T1.ItemSizeCd ,T1.HotColdCd
FROM startdb.Item T1
WHERE T1.ItemCat = 'COF';
ItemId ItemSizeCd HotColdCd
------ ---------- ---------
AMB BIG HOT
AMR REG HOT
CLB BIG HOT
CLR REG HOT
EINR REG HOT
FLTR REG HOT
IAMB BIG COLD
IAMR REG COLD
ICLB BIG COLD
ICLR REG COLD
IEINR REG COLD
IFLTR REG COLD
SQL
복사
이번에는 GROUP BY 처리한 SQL을 실행해보자. 아래와 같이 GROUP BY HotColdCd를 통해 나온 결과 집합의 UK는 GROUP BY 컬럼인 HotColdCd가 된다. HotColdCd는 결과 데이터 집합에서 중복되지 않는다.
-- [SQL-5-9-2]
SELECT T1.HotColdCd, COUNT(*) CNT
FROM startdb.Item T1
WHERE T1.ItemCat = 'COF'
GROUP BY T1.HotColdCd;
HotColdCd CNT
--------- ---
HOT 6
COLD 6
SQL
복사
GROUP BY가 처리된 데이터 집합은, GROUP BY 컬럼이 바로 UK가 된다. 아래 예는 Item 테이블을 ItemCat로 GROUP BY 처리했다. 그러므로 테이블에 있던 원래의 UK(PK)는 ItemId이지만, GROUP BY로 나온 데이터 집합의 UK는 ItemCat가 된다.
아래는 Ord(주문) 테이블의 데이터를 OrdYm, MemberId별로 GROUP BY 처리한 경우다. 테이블에 있을 때는 OrdNo가 UK지만, GROUP BY 처리된 데이터 집합의 UK는 OrdYm + MemberId가 된다.
SQL로 얻은 결과에 UK가 무엇인지 고민해보기 바란다. 만약에 UK가 없는 데이터 집합이 만들어졌다면 데이터를 잘 못 추출했을 가능성이 있다. UK를 정할 수 없다면 레코드에 중복이 있다는 뜻이며, 해당 데이터 집합으로 추가적인 작업을 진행하는데 어려움이 있을 수 있다.
BOOSTER QUIZ
BOOSTER QUIZ 5-9-1
아래 SQL로 얻은 결과 집합의 UK를 말하시오.
SELECT T1.MemberId ,DATE_FORMAT(T1.OrdDtm,'%Y%m%d') OrdYmd
,COUNT(*) OrdCnt
FROM startdb.Ord T1
WHERE T1.OrdDtm >= STR_TO_DATE('20231101','%Y%m%d')
AND T1.OrdDtm < STR_TO_DATE('20231201','%Y%m%d')
AND T1.OrdAmt >= 20000
GROUP BY T1.MemberId ,DATE_FORMAT(T1.OrdDtm,'%Y%m%d')
ORDER BY T1.MemberId ,OrdYmd;
SQL
복사
BOOSTER QUIZ 5-9-2
아래 SQL로 얻은 결과 집합의 UK를 말하시오.
SELECT T1.ShopId ,DATE_FORMAT(T1.OrdDtm,'%H') OrdHour ,T1.OrdSt
,SUM(T1.OrdAmt) SUM_OrdAmt
FROM startdb.Ord T1
WHERE T1.OrdDtm >= STR_TO_DATE('20231224','%Y%m%d')
AND T1.OrdDtm < STR_TO_DATE('20231225','%Y%m%d')
AND T1.OrdAmt >= 20000
GROUP BY T1.ShopId ,DATE_FORMAT(T1.OrdDtm,'%H') ,T1.OrdSt
SQL
복사