본문 바로가기
C.W.K.
Stream
Lesson 06 of 10 · published

GROUP BY와 HAVING

~14 min · sql, group-by, having

Level 0Scout
0 XP0/80 lessons0/10 achievements
0/120 XP to next level120 XP to go0% complete

묶어서 요약하기

GROUP BY가 row들을 지정한 컬럼 기준으로 버킷에 나눠 담고, 집계 함수가 버킷마다 한 번씩 돌아. HAVING은 집계가 끝난 다음에 버킷을 걸러내. WHERE와 대비해서 기억해. WHERE는 집계 전에 row를 걸러내거든.

연산 순서를 이렇게 그려두면 편해.

  1. FROM과 join이 후보 row를 모아.
  2. WHERE가 그 row를 걸러내.
  3. GROUP BY가 살아남은 row를 버킷에 나눠 담아.
  4. 집계 함수가 버킷마다 값 하나를 계산해.
  5. HAVING이 버킷을 걸러내.
  6. SELECT가 컬럼과 표현식을 골라 내보내.
  7. ORDER BYLIMIT이 마무리해.
Warning: SELECT한 컬럼 중 일부만 GROUP BY에 넣으면 Postgres는 에러를 내. SQLite는 그냥 통과시키고 집계 안 한 컬럼에는 아무 값이나 하나 골라 넣어. MySQL 5.7 이전과 똑같은 함정이지. 집계 안 한 SELECT 컬럼은 전부 GROUP BY에 넣거나 집계 함수로 감싸.

Code

GROUP BY + HAVING·sql
-- 이번 달 message count 기준 top 5 brain
SELECT brain, count(*) AS n
FROM   messages
WHERE  created_at >= datetime('now', 'start of month')
GROUP  BY brain
HAVING count(*) > 100      -- 트래픽 적은 brain 무시
ORDER  BY n DESC
LIMIT  5;
다중 컬럼 그룹·sql
-- per-day, per-brain message count
SELECT date(created_at)        AS day,
       brain,
       count(*)                AS n
FROM   messages
GROUP  BY day, brain
ORDER  BY day, brain;

External links

Exercise

row가 수백 개 들어간 작은 orders 테이블(id, customer_id, total, created_at)을 만들어. query 세 개를 써봐. 고객마다의 주문 수, 월별 매출 합계, 그리고 평생 쓴 금액 기준 상위 10명 고객인데 주문이 세 건 미만인 사람은 HAVING으로 빼는 것. 버킷 몇 개는 손으로 검산해봐.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.