03. SQL SELECT 명령어의 이해 및 실습

SELECT 명령어와 주요 절의 구조 — 데이터베이스에서 원하는 행과 열을 선별하고 정렬하기 위해 각 절을 조합한다.

1. 인트로

SELECT(셀렉트)는 데이터베이스에서 데이터를 조회하는 명령어이다.
SQL에서 가장 많이 사용되며, 리액트 앱에서 데이터를 화면에 표시할 때마다 SELECT가 사용된다.
이번 차시에서 SELECT의 기본 문법을 완전히 익힌다.


2. 실습 DB 준비

import sqlite3

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

# 게임 테이블 생성
cur.execute("""
    CREATE TABLE IF NOT EXISTS games (
        id       INTEGER PRIMARY KEY AUTOINCREMENT,
        title    TEXT    NOT NULL,
        genre    TEXT,
        platform TEXT,
        price    INTEGER,
        rating   REAL,
        release_yr INTEGER
    )
""")

# 샘플 데이터 삽입
games = [
    ("리그오브레전드",  "MOBA",  "PC",      0,    4.2, 2011),
    ("오버워치2",     "FPS",   "PC",      0,    3.8, 2022),
    ("스타크래프트2",  "RTS",   "PC",  24900,    4.5, 2010),
    ("마인크래프트",   "샌드박스", "PC",  29900,   4.8, 2011),
    ("엘든링",       "RPG",   "PS5", 69900,   4.9, 2022),
    ("제노버스",      "RPG",   "PS5", 59900,   4.1, 2015),
    ("젤다의전설",    "어드벤처", "Switch", 69900, 4.9, 2023),
    ("포켓몬스칼렛",  "RPG",   "Switch", 59900, 3.9, 2022),
    ("발로란트",      "FPS",   "PC",      0,    4.3, 2020),
    ("배틀그라운드",  "배틀로얄", "PC",  33000,   4.0, 2017),
]

cur.executemany(
    "INSERT INTO games (title, genre, platform, price, rating, release_yr) VALUES (?,?,?,?,?,?)",
    games
)
conn.commit()
print("게임 데이터 삽입 완료")

3. DB Browser 기반 DB 데이터 검토 실습

DB Browser for SQLite를 열고 game_store.db 파일을 열어 데이터를 확인한다.

  1. 데이터베이스 구조 탭: 테이블과 컬럼 구조를 확인한다.
  2. 데이터 탐색 탭: 삽입된 데이터를 표 형태로 확인한다.
  3. SQL 실행 탭: SQL 명령을 직접 입력하고 결과를 확인한다.

4. SQL SELECT 명령어의 이해 및 실습

4.1. 전체 조회 — SELECT *

cur.execute("SELECT * FROM games")
rows = cur.fetchall()
for r in rows:
    print(r)

코드 설명:

  • 1행: *는 모든 컬럼을 가져오라는 의미이다.
  • 3~4행: fetchall()로 전체 결과를 가져와 한 행씩 출력한다.

4.2. 특정 컬럼만 조회

cur.execute("SELECT title, price, rating FROM games")
rows = cur.fetchall()
for r in rows:
    print(f"제목: {r[0]:<15} 가격: {r[1]:>6}원  평점: {r[2]}")

코드 설명:

  • 1행: 가져올 컬럼명을 쉼표(,)로 구분하여 나열한다.
  • 4행: f-string으로 보기 좋게 정렬하여 출력한다.

4.3. WHERE(웨어) — 조건 검색

# RPG 게임만 조회
cur.execute("SELECT title, platform, price FROM games WHERE genre = 'RPG'")
rows = cur.fetchall()
print("=== RPG 게임 목록 ===")
for r in rows:
    print(f"  {r[0]} / {r[1]} / {r[2]}원")

코드 설명:

  • 2행: WHERE genre = 'RPG' — genre 컬럼 값이 'RPG'인 행만 가져온다.
  • 텍스트 조건은 작은따옴표(')로 감싼다.
# 무료 게임 조회
cur.execute("SELECT title, genre FROM games WHERE price = 0")
rows = cur.fetchall()
print("=== 무료 게임 ===")
for r in rows:
    print(f"  {r[0]} ({r[1]})")

4.4. 비교 연산자 & 논리 연산자

# 평점 4.5 이상이면서 PC 플랫폼인 게임
cur.execute("""
    SELECT title, rating, platform
    FROM games
    WHERE rating >= 4.5 AND platform = 'PC'
""")
rows = cur.fetchall()
for r in rows:
    print(r)

코드 설명:

  • 5행: AND — 두 조건을 모두 만족하는 행만 가져온다.
  • OR — 둘 중 하나만 만족해도 가져온다.
  • NOT — 조건을 만족하지 않는 행을 가져온다.
# PC 또는 PS5 게임 조회
cur.execute("SELECT title, platform FROM games WHERE platform = 'PC' OR platform = 'PS5'")
rows = cur.fetchall()
for r in rows:
    print(r)

4.5. LIKE(라이크) — 부분 검색

# 제목에 '오버'가 포함된 게임
cur.execute("SELECT title FROM games WHERE title LIKE '%오버%'")
rows = cur.fetchall()
for r in rows:
    print(r)

코드 설명:

  • 2행: LIKE '%오버%' — %는 임의의 문자열을 의미한다.
    • %오버 — '오버'로 끝나는 값
    • 오버% — '오버'로 시작하는 값
    • %오버% — '오버'를 포함하는 값

4.6. ORDER BY(오더 바이) — 정렬

# 평점 높은 순으로 정렬
cur.execute("SELECT title, rating FROM games ORDER BY rating DESC")
rows = cur.fetchall()
print("=== 평점 순위 ===")
for i, r in enumerate(rows, 1):
    print(f"  {i}위: {r[0]} ({r[1]})")

코드 설명:

  • 2행: ORDER BY rating DESC — rating 기준으로 내림차순(높은 → 낮은) 정렬한다.
  • ASC — 오름차순 (낮은 → 높은), 기본값이다.
  • 5행: enumerate(rows, 1) — 인덱스를 1부터 시작하여 순위를 매긴다.

4.7. LIMIT(리밋) — 개수 제한

LIMIT 3만으로는 평점이 높은 게임 3개를 고를 수 없습니다. 아래 예제는 ORDER BY rating DESC로 평점이 높은 순서로 정렬한 뒤 3개를 가져옵니다. 평점이 같은 행끼리의 순서는 이 예제에서 정하지 않았습니다. 같은 DB 내용에서 동점의 순서까지 일정하게 정하려면 각 행을 구분하는 보조 정렬 기준이 필요합니다. 이 실습의 id는 기본 키이므로 ORDER BY rating DESC, id ASC LIMIT 3처럼 정하면 평점이 같은 행은 id가 작은 순서로 선택됩니다. SQLite 공식 ORDER BY 설명에서 정렬을 지정하지 않은 결과와 동률의 순서가 정해지지 않는다는 점을 확인할 수 있습니다.

# 평점 TOP 3 조회
cur.execute("SELECT title, rating FROM games ORDER BY rating DESC LIMIT 3")
rows = cur.fetchall()
print("=== 평점 TOP 3 ===")
for r in rows:
    print(f"  {r[0]} : {r[1]}")

코드 설명:

  • 2행: LIMIT 3 — 조건에 맞는 결과 중 위에서 3개만 가져온다.

5. 활용 Plus — pandas와 함께

import pandas as pd

df = pd.read_sql("SELECT title, genre, rating FROM games ORDER BY rating DESC", conn)
print(df)

실행 결과 (상위 5행):

         title   genre  rating
0      젤다의전설   어드벤처     4.9
1         엘든링     RPG     4.9
2       마인크래프트   샌드박스     4.8
3      스타크래프트2     RTS     4.5
4        발로란트     FPS     4.3

6. 문제풀기

Q1. SELECT에서 특정 컬럼만 가져오려면 어떻게 하는가?

SELECT 컬럼1, 컬럼2 FROM 테이블명;

여러 컬럼은 쉼표(,)로 구분한다.

Q2. LIKE ‘%전설’의 의미는?

‘전설’로 끝나는 모든 문자열을 검색한다.

예: ‘젤다의전설’은 해당하고, ‘전설의 검’은 해당하지 않는다.

Q3. 가격이 30000원 이상이고 평점이 4.5 이상인 게임을 조회하는 SQL을 작성하시오.

SELECT title, price, rating FROM games WHERE price >= 30000 AND rating >= 4.5;

Q4. ORDER BY DESC와 ASC의 차이는?

DESC(내림차순): 큰 값에서 작은 값 순서로 정렬한다.

ASC(오름차순): 작은 값에서 큰 값 순서로 정렬한다. 기본값이다.

댓글 남기기