🐨CoalaCoding
DocsExamplesTry itBoardB반
🐨CoalaCoding

개발자를 위한 한국어 웹 기술 문서

문서

  • JavaScript
  • Web Publishing
  • React
  • Python

커뮤니티

  • 게시판
  • 예제 모음
  • Try it 에디터

기타

  • GitHub
  • 관리자
© 2026 CoalaCoding. All rights reserved.
  • 01_sqlite3로 SQL 명령문 실행
  • 02_DB데이터 일괄추가하기
  • 03_SQLite3 라이브러리를 활용한 SQL 명령문 실행
  • 04_Pandas를 활용한 SQL 명령문 실행
  • 05_CREATE 명령어를 활용한 DB 테이블의 생성
  • 06_DDL 명령어의 이해 및 실습
  • 07_SQL SELECT 명령어의 이해 및 실습
  • 08_SQL INSERT, UPDATE, DELETE 명령어 실습
  • 09_SQL SELECT 세부 명령어 실습 1
  • 10_SQL SELECT 세부 명령어 실습 2
  • 11_SQL INNER JOIN 실습
  • 12_SQL LEFT JOIN 실습
  • 13_SQL GROUP BY 실습 1
  • 14_SQL GROUP BY 실습 2
  • 15_SQL SubQuery 활용 실습
  • 16_데이터셋 기반 DB 구축 & DB 활용 실습 — 리액트 연동 완성
  1. 홈
  2. 문서
  3. Backend
  4. Database & SQL
  5. 13_SQL GROUP BY 실습 1

13_SQL GROUP BY 실습 1

코드 블록의 Try it Yourself 버튼으로 직접 실행할 수 있다.

구문

1. 인트로

GROUP BY(그룹 바이)는 같은 값을 가진 행들을 묶어 집계 함수로 통계를 구하는 기능이다. "장르별 게임 수", "월별 매출", "카테고리별 평균 가격" 같은 통계 데이터를 만들 때 반드시 필요하다.


2. 실습 DB 준비 (7차시 game_store.db 이어서 사용)

import sqlite3
import pandas as pd

conn = sqlite3.connect("game_store.db")
cur  = conn.cursor()

# 데이터 확인
df = pd.read_sql("SELECT * FROM games", conn)
print(df[["title","genre","platform","price","rating"]])

3. GROUP BY(그룹 바이) 명령어 실습

3.1. GROUP BY 기본 개념

GROUP BY는 특정 컬럼의 값이 같은 행들을 하나의 그룹으로 묶는다.

플랫폼이 'PC'인 행들  → PC 그룹
플랫폼이 'PS5'인 행들 → PS5 그룹
플랫폼이 'Switch'인 행들 → Switch 그룹

각 그룹에 COUNT(), AVG(), SUM(), MAX(), MIN() 같은 집계 함수를 적용한다.

3.2. 주요 집계 함수

함수의미
COUNT(컬럼)행의 수를 센다
SUM(컬럼)합계를 구한다
AVG(컬럼)평균을 구한다
MAX(컬럼)최대값을 구한다
MIN(컬럼)최소값을 구한다

3.3. 플랫폼별 게임 수 집계

df = pd.read_sql("""
    SELECT platform       AS 플랫폼,
           COUNT(id)      AS 게임수
    FROM games
    GROUP BY platform
    ORDER BY 게임수 DESC
""", conn)
print("=== 플랫폼별 게임 수 ===")
print(df)

코드 설명:

  • 3행: COUNT(id) — 그룹 내 행의 수를 센다.
  • 5행: GROUP BY platform — platform 값이 같은 행끼리 묶는다.
  • SELECT에는 GROUP BY 기준 컬럼과 집계 함수만 사용할 수 있다.

3.4. 장르별 평균 평점

df = pd.read_sql("""
    SELECT genre          AS 장르,
           COUNT(id)      AS 게임수,
           ROUND(AVG(rating), 2) AS 평균평점,
           MAX(rating)    AS 최고평점
    FROM games
    GROUP BY genre
    ORDER BY 평균평점 DESC
""", conn)
print("=== 장르별 통계 ===")
print(df)

코드 설명:

  • 4행: ROUND(AVG(rating), 2) — 평균 평점을 소수점 둘째 자리까지 반올림한다.
  • ROUND(값, 자릿수) — 지정한 자릿수로 반올림한다.

4. HAVING(해빙) 명령어 실습

4.1. HAVING이란?

WHERE는 개별 행을 필터링한다. HAVING은 GROUP BY로 묶인 그룹을 필터링한다.

WHERE  → 그룹화 전에 행을 필터링
HAVING → 그룹화 후에 그룹을 필터링

4.2. 게임이 2개 이상인 플랫폼만 조회

df = pd.read_sql("""
    SELECT platform  AS 플랫폼,
           COUNT(id) AS 게임수
    FROM games
    GROUP BY platform
    HAVING COUNT(id) >= 2
    ORDER BY 게임수 DESC
""", conn)
print("=== 게임 2개 이상 플랫폼 ===")
print(df)

코드 설명:

  • 6행: HAVING COUNT(id) >= 2 — 그룹화 후 게임 수가 2개 이상인 그룹만 남긴다.
  • WHERE에는 집계 함수를 쓸 수 없으나 HAVING에는 쓸 수 있다.

4.3. HAVING 명령어 실습 — 평균 평점 4.5 이상인 장르

df = pd.read_sql("""
    SELECT genre              AS 장르,
           COUNT(id)          AS 게임수,
           ROUND(AVG(rating), 1) AS 평균평점
    FROM games
    GROUP BY genre
    HAVING AVG(rating) >= 4.5
    ORDER BY 평균평점 DESC
""", conn)
print("=== 평균 평점 4.5+ 장르 ===")
print(df)

5. GROUP BY & JOIN 동시 적용 실습

# JOIN + GROUP BY: 플랫폼별 유료 게임의 평균 가격과 최고 평점
df = pd.read_sql("""
    SELECT platform          AS 플랫폼,
           COUNT(id)         AS 유료게임수,
           ROUND(AVG(price), 0) AS 평균가격,
           MAX(rating)       AS 최고평점
    FROM games
    WHERE price > 0
    GROUP BY platform
    HAVING COUNT(id) >= 1
    ORDER BY 평균가격 DESC
""", conn)
print("=== 플랫폼별 유료게임 통계 ===")
print(df)

코드 설명:

  • 8행: WHERE price > 0 — 그룹화 전에 무료 게임을 제외한다.
  • 10행: HAVING COUNT(id) >= 1 — 유료 게임이 1개 이상인 플랫폼만 표시한다.
  • WHERE와 HAVING이 함께 쓰일 때 실행 순서: WHERE 먼저 → GROUP BY → HAVING

6. 활용 Plus — 리액트 대시보드 연동

리액트 게임 스토어 앱의 "통계 대시보드" 페이지에서 파이썬 API가 반환하는 데이터 예시이다.

def get_stats():
    stats = {}

    # 플랫폼별 게임 수
    df1 = pd.read_sql(
        "SELECT platform, COUNT(*) AS cnt FROM games GROUP BY platform",
        conn
    )
    stats["by_platform"] = df1.to_dict("records")

    # 장르별 평균 평점
    df2 = pd.read_sql(
        "SELECT genre, ROUND(AVG(rating),2) AS avg_r FROM games GROUP BY genre",
        conn
    )
    stats["by_genre"] = df2.to_dict("records")

    return stats

import json
print(json.dumps(get_stats(), ensure_ascii=False, indent=2))

코드 설명:

  • 2행: 여러 통계를 딕셔너리에 담아 한 번에 반환한다.
  • 21행: json.dumps()로 JSON 문자열로 변환하여 출력한다. 리액트 API 응답 형태이다.

7. 문제풀기

목차

  • 구문