데이터베이스에서 데이터를 분석할 때 가장 자주 사용하는 기능 중 하나가 바로 그룹화와 집계입니다. 오늘은 카페 운영 시나리오를 통해 SQL의 GROUP BY, ORDER BY, HAVING 절과 주요 집계함수들을 쉽고 재미있게 알아보겠습니다!
데이터 그룹화의 마법: GROUP BY
여러분이 카페를 운영한다고 상상해보세요. 매일매일 다양한 메뉴의 매출을 기록하고 있는데, "어떤 메뉴가 가장 잘 팔릴까?"라는 궁금증이 생겼습니다. 이럴 때 딱 필요한 것이 바로 GROUP BY입니다!
샘플 데이터
| sale_date | item | sales |
|------------|--------------|-------|
| 2024-09-01 | Coffee | 5000 |
| 2024-09-01 | Cake | 7000 |
| 2024-09-01 | Tea | 3000 |
| 2024-09-02 | Coffee | 6000 |
| 2024-09-02 | Cake | 8000 |
| 2024-09-02 | Tea | 4000 |
| 2024-09-03 | Coffee | 5500 |
| 2024-09-03 | Cake | 7500 |
| 2024-09-03 | Tea | 3500 |
메뉴별 총 매출 구하기
SELECT item, SUM(sales) AS total_sales
FROM cafe_sales
GROUP BY item;
결과:
| item | total_sales |
|---------|-------------|
| Coffee | 16500 |
| Cake | 22500 |
| Tea | 10500 |
GROUP BY는 일별로 흩어져 있는 매출 데이터를 메뉴별로 묶어주는 역할을 합니다. 마치 비슷한 색깔의 구슬들을 하나씩 모아 놓는 것과 같아요!
데이터 정렬하기: ORDER BY
메뉴가 많아지면 어떤 것이 효자 메뉴인지 한눈에 보기 어려워집니다. 이때 ORDER BY를 사용하면 매출 순으로 깔끔하게 정렬할 수 있어요!
SELECT item, SUM(sales) AS total_sales
FROM cafe_sales
GROUP BY item
ORDER BY total_sales DESC;
결과:
| item | total_sales |
|---------|-------------|
| Cake | 22500 |
| Coffee | 16500 |
| Tea | 10500 |
- DESC: 내림차순 정렬 (높은 값부터)
- ASC: 오름차순 정렬 (낮은 값부터, 기본값)
이제 케이크가 1등, 커피가 2등이라는 것을 한눈에 알 수 있습니다!
고매출 메뉴만 걸러내기: HAVING
전투력(매출액)이 일정 수준 이상인 메뉴만 보고 싶다면? HAVING 절을 사용합니다!
SELECT item, SUM(sales) AS total_sales
FROM cafe_sales
GROUP BY item
HAVING total_sales >= 15000
ORDER BY total_sales DESC;
결과:
| item | total_sales |
|---------|-------------|
| Cake | 22500 |
| Coffee | 16500 |
💡 WHERE vs HAVING
- WHERE: 행(row) 단위에서 조건을 걸 때 사용
- HAVING: 그룹화된 결과에 조건을 걸 때 사용
집계함수 완전정복
집계함수는 데이터를 요약하고 계산할 때 사용하는 핵심 도구들입니다. GROUP BY와 함께 사용되어 강력한 데이터 분석을 가능하게 해줍니다!
1. SUM() - 합계 구하기
SELECT item, SUM(sales) AS total_sales
FROM cafe_sales
GROUP BY item;
숫자형 데이터의 총합을 계산합니다. 매출, 비용, 점수 등의 합계를 구할 때 필수적이에요!
2. AVG() - 평균값 구하기
SELECT item, AVG(sales) AS average_sales
FROM cafe_sales
GROUP BY item;
결과:
| item | average_sales |
|---------|---------------|
| Coffee | 5500 |
| Cake | 7500 |
| Tea | 3500 |
각 메뉴의 일평균 매출을 알 수 있어서 안정적인 매출 패턴을 파악할 수 있습니다.
3. COUNT() - 개수 세기
매출 빈도를 확인하는 것도 중요합니다. 매출액은 높지만 특정 날짜에만 집중된 노이즈성 데이터일 수 있거든요!
SELECT sale_date, item, COUNT(*) AS sale_count
FROM cafe_sales
GROUP BY sale_date, item;
COUNT(*)를 사용하는 이유
- COUNT(*): NULL 값을 포함한 모든 행의 개수를 셈
- COUNT(column_name): 해당 컬럼에서 NULL이 아닌 값의 개수만 셈
- 성능상 COUNT(*)가 더 효율적입니다!
4. 기타 유용한 집계함수들
-- 최댓값
SELECT item, MAX(sales) AS max_sales
FROM cafe_sales
GROUP BY item;
-- 최솟값
SELECT item, MIN(sales) AS min_sales
FROM cafe_sales
GROUP BY item;
⚠️ 주의사항: only_full_group_by 모드
MySQL 8에서는 only_full_group_by 모드가 기본 활성화되어 있습니다. 이는 GROUP BY 사용 시 비집계 컬럼(집계함수가 붙지 않은 컬럼)을 SELECT에 포함하는 것을 허용하지 않는 규칙입니다.
-- ❌ 에러 발생
SELECT item, sales, SUM(sales)
FROM cafe_sales
GROUP BY item;
-- ✅ 올바른 사용
SELECT item, SUM(sales) AS total_sales
FROM cafe_sales
GROUP BY item;
이 규칙은 쿼리의 일관성과 정확성을 높이기 위해 도입되었으니 꼭 지켜주세요!
정리
- GROUP BY: 데이터를 특정 기준으로 그룹화
- ORDER BY: 결과를 정렬 (DESC: 내림차순, ASC: 오름차순)
- HAVING: 그룹화된 결과에 조건 적용
- 집계함수: SUM, AVG, COUNT, MAX, MIN 등으로 데이터 요약
이제 여러분도 SQL 마법사가 되어 데이터를 자유자재로 요리할 수 있을 거예요! 카페 사장이 되어도, 데이터 분석가가 되어도 이 기술들은 여러분의 든든한 동반자가 될 것입니다.
'Daily Logs > TIL (Today I Learned)' 카테고리의 다른 글
DB part.4 (1) | 2025.06.10 |
---|---|
DB part.3 (0) | 2025.06.09 |
DB part.1 (4) | 2025.06.07 |
JWT (Json Web Token) (1) | 2025.05.22 |
Package Manager (npm,yarn,pnpm) (0) | 2025.01.15 |