[Python 100일 챌린지] Day 74 - SQL 기본 (SELECT, WHERE)
[Python 100일 챌린지] Day 74 - SQL 기본 (SELECT, WHERE)
데이터베이스의 진짜 힘은 검색에서 나옵니다! 테이블에 수만 개의 데이터가 있어도, SELECT와 WHERE를 사용하면 원하는 정보를 정확하게 찾아낼 수 있어요. 오늘 배울 내용은 SQL의 핵심이자 가장 자주 사용하는 기능입니다. 조건을 조합하고 정렬하고 제한하는 방법까지, 데이터 조회의 모든 것을 마스터해봅시다! 😊
(30분 완독 ⭐⭐⭐)
🎯 오늘의 학습 목표
📚 사전 지식
- Day 72: SQLite 시작하기 - SQLite 연결 및 기본 사용법
- Day 73: SQL 기본 (CREATE, INSERT) - 테이블 생성 및 데이터 추가
🎯 학습 목표 1: SELECT로 데이터 조회하기
한 줄 설명
SELECT = 데이터베이스에서 원하는 데이터 가져오기
테이블의 모든 데이터 또는 특정 컬럼만 선택해서 조회합니다.
기본 SELECT 문법
1
SELECT 컬럼명1, 컬럼명2 FROM 테이블명;
모든 컬럼 조회 (*)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import sqlite3
# 샘플 데이터 준비
conn = sqlite3.connect('shop.db')
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS products (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT,
price REAL,
stock INTEGER,
category TEXT
)
''')
products = [
('노트북', 1200000, 10, '전자제품'),
('마우스', 25000, 50, '전자제품'),
('책상', 150000, 15, '가구'),
('의자', 80000, 20, '가구'),
('키보드', 65000, 30, '전자제품')
]
cursor.executemany('INSERT INTO products (name, price, stock, category) VALUES (?, ?, ?, ?)', products)
conn.commit()
# 모든 컬럼 조회
cursor.execute('SELECT * FROM products')
rows = cursor.fetchall()
print("=== 전체 상품 목록 ===")
for row in rows:
print(row)
conn.close()
출력:
1
2
3
4
5
6
=== 전체 상품 목록 ===
(1, '노트북', 1200000.0, 10, '전자제품')
(2, '마우스', 25000.0, 50, '전자제품')
(3, '책상', 150000.0, 15, '가구')
(4, '의자', 80000.0, 20, '가구')
(5, '키보드', 65000.0, 30, '전자제품')
특정 컬럼만 조회
1
2
3
4
5
6
7
8
# 상품명과 가격만 조회
cursor.execute('SELECT name, price FROM products')
rows = cursor.fetchall()
print("=== 상품명과 가격 ===")
for row in rows:
name, price = row
print(f"{name}: {price:,}원")
출력:
1
2
3
4
5
6
=== 상품명과 가격 ===
노트북: 1,200,000원
마우스: 25,000원
책상: 150,000원
의자: 80,000원
키보드: 65,000원
fetchone(), fetchall(), fetchmany()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import sqlite3
conn = sqlite3.connect('shop.db')
cursor = conn.cursor()
# fetchone() - 한 행만 가져오기
cursor.execute('SELECT * FROM products')
first_row = cursor.fetchone()
print("첫 번째 상품:", first_row)
# fetchall() - 모든 행 가져오기
cursor.execute('SELECT * FROM products')
all_rows = cursor.fetchall()
print(f"\n전체 {len(all_rows)}개 상품")
# fetchmany(n) - n개 행 가져오기
cursor.execute('SELECT * FROM products')
three_rows = cursor.fetchmany(3)
print(f"\n처음 3개 상품:")
for row in three_rows:
print(row[1]) # 상품명만 출력
conn.close()
출력:
1
2
3
4
5
6
7
8
첫 번째 상품: (1, '노트북', 1200000.0, 10, '전자제품')
전체 5개 상품
처음 3개 상품:
노트북
마우스
책상
🎯 학습 목표 2: WHERE로 조건 필터링하기
WHERE 기본 문법
1
SELECT * FROM 테이블명 WHERE 조건;
비교 연산자 (=, <>, <, >, <=, >=)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import sqlite3
conn = sqlite3.connect('shop.db')
cursor = conn.cursor()
# 1. 같음 (=)
cursor.execute('SELECT * FROM products WHERE category = "전자제품"')
electronics = cursor.fetchall()
print("=== 전자제품 목록 ===")
for product in electronics:
print(f"{product[1]}: {product[2]:,}원")
# 2. 같지 않음 (<> 또는 !=)
cursor.execute('SELECT * FROM products WHERE category <> "전자제품"')
non_electronics = cursor.fetchall()
print("\n=== 전자제품이 아닌 상품 ===")
for product in non_electronics:
print(f"{product[1]}: {product[4]}")
# 3. 크다 (>)
cursor.execute('SELECT * FROM products WHERE price > 100000')
expensive = cursor.fetchall()
print("\n=== 10만원 초과 상품 ===")
for product in expensive:
print(f"{product[1]}: {product[2]:,}원")
# 4. 작거나 같음 (<=)
cursor.execute('SELECT * FROM products WHERE stock <= 20')
low_stock = cursor.fetchall()
print("\n=== 재고 20개 이하 상품 ===")
for product in low_stock:
print(f"{product[1]}: 재고 {product[3]}개")
conn.close()
출력:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
=== 전자제품 목록 ===
노트북: 1,200,000원
마우스: 25,000원
키보드: 65,000원
=== 전자제품이 아닌 상품 ===
책상: 가구
의자: 가구
=== 10만원 초과 상품 ===
노트북: 1,200,000원
책상: 150,000원
=== 재고 20개 이하 상품 ===
노트북: 재고 10개
책상: 재고 15개
의자: 재고 20개
논리 연산자 (AND, OR, NOT)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import sqlite3
conn = sqlite3.connect('shop.db')
cursor = conn.cursor()
# AND - 모든 조건 만족
cursor.execute('''
SELECT * FROM products
WHERE category = "전자제품" AND price < 100000
''')
affordable_electronics = cursor.fetchall()
print("=== 10만원 미만 전자제품 ===")
for product in affordable_electronics:
print(f"{product[1]}: {product[2]:,}원")
# OR - 하나 이상의 조건 만족
cursor.execute('''
SELECT * FROM products
WHERE price > 1000000 OR stock > 40
''')
high_value_or_stock = cursor.fetchall()
print("\n=== 100만원 초과 또는 재고 40개 초과 ===")
for product in high_value_or_stock:
print(f"{product[1]}: {product[2]:,}원, 재고 {product[3]}개")
# NOT - 조건을 만족하지 않음
cursor.execute('''
SELECT * FROM products
WHERE NOT category = "전자제품"
''')
not_electronics = cursor.fetchall()
print("\n=== 전자제품 제외 ===")
for product in not_electronics:
print(f"{product[1]}: {product[4]}")
# 복합 조건 (AND와 OR 혼합)
cursor.execute('''
SELECT * FROM products
WHERE (category = "전자제품" AND price < 100000)
OR (category = "가구" AND stock > 15)
''')
complex_condition = cursor.fetchall()
print("\n=== 복합 조건 결과 ===")
for product in complex_condition:
print(f"{product[1]}: {product[4]}, {product[2]:,}원")
conn.close()
출력:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
=== 10만원 미만 전자제품 ===
마우스: 25,000원
키보드: 65,000원
=== 100만원 초과 또는 재고 40개 초과 ===
노트북: 1,200,000원, 재고 10개
마우스: 25,000원, 재고 50개
=== 전자제품 제외 ===
책상: 가구
의자: 가구
=== 복합 조건 결과 ===
마우스: 전자제품, 25,000원
의자: 가구, 80,000원
키보드: 전자제품, 65,000원
LIKE 패턴 매칭
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import sqlite3
conn = sqlite3.connect('shop.db')
cursor = conn.cursor()
# % - 0개 이상의 임의 문자
cursor.execute('SELECT * FROM products WHERE name LIKE "노%"')
starts_with = cursor.fetchall()
print("=== '노'로 시작하는 상품 ===")
for product in starts_with:
print(product[1])
# %키% - '키'를 포함하는 모든 상품
cursor.execute('SELECT * FROM products WHERE name LIKE "%키%"')
contains = cursor.fetchall()
print("\n=== '키'를 포함하는 상품 ===")
for product in contains:
print(product[1])
# _ - 정확히 1개의 임의 문자
cursor.execute('SELECT * FROM products WHERE name LIKE "_자"')
one_char = cursor.fetchall()
print("\n=== 2글자이며 '자'로 끝나는 상품 ===")
for product in one_char:
print(product[1])
conn.close()
출력:
1
2
3
4
5
6
7
8
=== '노'로 시작하는 상품 ===
노트북
=== '키'를 포함하는 상품 ===
키보드
=== 2글자이며 '자'로 끝나는 상품 ===
의자
BETWEEN과 IN
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import sqlite3
conn = sqlite3.connect('shop.db')
cursor = conn.cursor()
# BETWEEN - 범위 조건
cursor.execute('''
SELECT * FROM products
WHERE price BETWEEN 50000 AND 200000
''')
in_range = cursor.fetchall()
print("=== 5만원 ~ 20만원 상품 ===")
for product in in_range:
print(f"{product[1]}: {product[2]:,}원")
# IN - 여러 값 중 하나
cursor.execute('''
SELECT * FROM products
WHERE name IN ("마우스", "키보드", "의자")
''')
specific_items = cursor.fetchall()
print("\n=== 마우스, 키보드, 의자 ===")
for product in specific_items:
print(f"{product[1]}: {product[2]:,}원")
# NOT IN
cursor.execute('''
SELECT * FROM products
WHERE category NOT IN ("전자제품")
''')
not_in = cursor.fetchall()
print("\n=== 전자제품 제외 ===")
for product in not_in:
print(f"{product[1]}: {product[4]}")
conn.close()
출력:
1
2
3
4
5
6
7
8
9
10
11
12
13
=== 5만원 ~ 20만원 상품 ===
책상: 150,000원
의자: 80,000원
키보드: 65,000원
=== 마우스, 키보드, 의자 ===
마우스: 25,000원
의자: 80,000원
키보드: 65,000원
=== 전자제품 제외 ===
책상: 가구
의자: 가구
🎯 학습 목표 3: 정렬과 제한으로 결과 제어하기
ORDER BY (정렬)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import sqlite3
conn = sqlite3.connect('shop.db')
cursor = conn.cursor()
# 오름차순 정렬 (ASC - 기본값)
cursor.execute('SELECT * FROM products ORDER BY price ASC')
asc_products = cursor.fetchall()
print("=== 가격 낮은 순 ===")
for product in asc_products:
print(f"{product[1]}: {product[2]:,}원")
# 내림차순 정렬 (DESC)
cursor.execute('SELECT * FROM products ORDER BY price DESC')
desc_products = cursor.fetchall()
print("\n=== 가격 높은 순 ===")
for product in desc_products:
print(f"{product[1]}: {product[2]:,}원")
# 다중 컬럼 정렬
cursor.execute('''
SELECT * FROM products
ORDER BY category ASC, price DESC
''')
multi_sort = cursor.fetchall()
print("\n=== 카테고리별, 가격 높은 순 ===")
for product in multi_sort:
print(f"{product[4]}: {product[1]} ({product[2]:,}원)")
conn.close()
출력:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
=== 가격 낮은 순 ===
마우스: 25,000원
키보드: 65,000원
의자: 80,000원
책상: 150,000원
노트북: 1,200,000원
=== 가격 높은 순 ===
노트북: 1,200,000원
책상: 150,000원
의자: 80,000원
키보드: 65,000원
마우스: 25,000원
=== 카테고리별, 가격 높은 순 ===
가구: 책상 (150,000원)
가구: 의자 (80,000원)
전자제품: 노트북 (1,200,000원)
전자제품: 키보드 (65,000원)
전자제품: 마우스 (25,000원)
LIMIT과 OFFSET (제한)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import sqlite3
conn = sqlite3.connect('shop.db')
cursor = conn.cursor()
# LIMIT - 결과 개수 제한
cursor.execute('SELECT * FROM products ORDER BY price DESC LIMIT 3')
top3 = cursor.fetchall()
print("=== 가장 비싼 상품 TOP 3 ===")
for i, product in enumerate(top3, 1):
print(f"{i}위: {product[1]} ({product[2]:,}원)")
# LIMIT + OFFSET - 페이징
print("\n=== 페이지 1 (첫 2개) ===")
cursor.execute('SELECT * FROM products LIMIT 2 OFFSET 0')
page1 = cursor.fetchall()
for product in page1:
print(product[1])
print("\n=== 페이지 2 (다음 2개) ===")
cursor.execute('SELECT * FROM products LIMIT 2 OFFSET 2')
page2 = cursor.fetchall()
for product in page2:
print(product[1])
conn.close()
출력:
1
2
3
4
5
6
7
8
9
10
11
12
=== 가장 비싼 상품 TOP 3 ===
1위: 노트북 (1,200,000원)
2위: 책상 (150,000원)
3위: 의자 (80,000원)
=== 페이지 1 (첫 2개) ===
노트북
마우스
=== 페이지 2 (다음 2개) ===
책상
의자
🎯 학습 목표 4: 고급 검색 패턴 익히기
NULL 값 처리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
import sqlite3
conn = sqlite3.connect('shop.db')
cursor = conn.cursor()
# 테스트용 NULL 데이터 추가
cursor.execute('''
INSERT INTO products (name, price, stock, category)
VALUES ("미정상품", NULL, 0, NULL)
''')
conn.commit()
# IS NULL - NULL 값 찾기
cursor.execute('SELECT * FROM products WHERE category IS NULL')
null_category = cursor.fetchall()
print("=== 카테고리가 없는 상품 ===")
for product in null_category:
print(f"{product[1]}: 카테고리 미정")
# IS NOT NULL - NULL이 아닌 값 찾기
cursor.execute('SELECT * FROM products WHERE price IS NOT NULL')
has_price = cursor.fetchall()
print(f"\n=== 가격 정보가 있는 상품: {len(has_price)}개 ===")
conn.close()
집계 함수와 함께 사용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import sqlite3
conn = sqlite3.connect('shop.db')
cursor = conn.cursor()
# COUNT - 개수 세기
cursor.execute('SELECT COUNT(*) FROM products')
total_count = cursor.fetchone()[0]
print(f"전체 상품 수: {total_count}개")
# COUNT with WHERE
cursor.execute('SELECT COUNT(*) FROM products WHERE category = "전자제품"')
electronics_count = cursor.fetchone()[0]
print(f"전자제품 수: {electronics_count}개")
# SUM - 합계
cursor.execute('SELECT SUM(stock) FROM products WHERE category = "전자제품"')
total_electronics_stock = cursor.fetchone()[0]
print(f"전자제품 총 재고: {total_electronics_stock}개")
# AVG - 평균
cursor.execute('SELECT AVG(price) FROM products WHERE price IS NOT NULL')
avg_price = cursor.fetchone()[0]
print(f"평균 가격: {avg_price:,.0f}원")
# MIN, MAX - 최소/최대
cursor.execute('SELECT MIN(price), MAX(price) FROM products WHERE price IS NOT NULL')
min_price, max_price = cursor.fetchone()
print(f"최저가: {min_price:,}원, 최고가: {max_price:,}원")
conn.close()
출력:
1
2
3
4
5
전체 상품 수: 6개
전자제품 수: 3개
전자제품 총 재고: 90개
평균 가격: 308,000원
최저가: 25,000원, 최고가: 1,200,000원
실전 예제: 상품 검색 시스템
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import sqlite3
def search_products(keyword=None, category=None, min_price=None, max_price=None, order_by='name'):
"""다양한 조건으로 상품 검색"""
conn = sqlite3.connect('shop.db')
cursor = conn.cursor()
# 기본 쿼리
query = "SELECT * FROM products WHERE 1=1"
params = []
# 동적 조건 추가
if keyword:
query += " AND name LIKE ?"
params.append(f"%{keyword}%")
if category:
query += " AND category = ?"
params.append(category)
if min_price is not None:
query += " AND price >= ?"
params.append(min_price)
if max_price is not None:
query += " AND price <= ?"
params.append(max_price)
# 정렬 추가
query += f" ORDER BY {order_by}"
# 실행
cursor.execute(query, params)
results = cursor.fetchall()
conn.close()
return results
# 테스트
print("=== 검색 1: '키' 포함 상품 ===")
results = search_products(keyword='키')
for product in results:
print(f"{product[1]}: {product[2]:,}원")
print("\n=== 검색 2: 전자제품, 5만원~10만원 ===")
results = search_products(category='전자제품', min_price=50000, max_price=100000)
for product in results:
print(f"{product[1]}: {product[2]:,}원")
print("\n=== 검색 3: 모든 상품, 가격 높은 순 ===")
results = search_products(order_by='price DESC')
for product in results[:3]: # 상위 3개만
print(f"{product[1]}: {product[2]:,}원" if product[2] else f"{product[1]}: 가격 미정")
출력:
1
2
3
4
5
6
7
8
9
10
=== 검색 1: '키' 포함 상품 ===
키보드: 65,000원
=== 검색 2: 전자제품, 5만원~10만원 ===
키보드: 65,000원
=== 검색 3: 모든 상품, 가격 높은 순 ===
노트북: 1,200,000원
책상: 150,000원
의자: 80,000원
💡 실전 팁 & 주의사항
💡 Tip 1: 인덱스 활용으로 검색 속도 향상
1
2
3
4
5
6
# 자주 검색하는 컬럼에 인덱스 생성
cursor.execute('CREATE INDEX idx_category ON products(category)')
cursor.execute('CREATE INDEX idx_price ON products(price)')
# WHERE절에서 해당 컬럼 사용 시 검색 속도 대폭 향상
cursor.execute('SELECT * FROM products WHERE category = "전자제품"')
💡 Tip 2: LIKE 사용 시 주의사항
1
2
3
4
5
# ❌ 느림 - 앞에 %가 있으면 인덱스 사용 불가
cursor.execute('SELECT * FROM products WHERE name LIKE "%북"')
# ✅ 빠름 - 앞에 고정 문자가 있으면 인덱스 활용 가능
cursor.execute('SELECT * FROM products WHERE name LIKE "노%"')
💡 Tip 3: SQL Injection 방지
1
2
3
4
5
6
# ❌ 위험! - SQL Injection 취약
category = "전자제품"
cursor.execute(f"SELECT * FROM products WHERE category = '{category}'")
# ✅ 안전 - 플레이스홀더 사용
cursor.execute("SELECT * FROM products WHERE category = ?", (category,))
💡 Tip 4: NULL 비교는 IS 사용
1
2
3
4
5
6
# ❌ 작동 안 함
cursor.execute('SELECT * FROM products WHERE price = NULL')
# ✅ 올바른 방법
cursor.execute('SELECT * FROM products WHERE price IS NULL')
cursor.execute('SELECT * FROM products WHERE price IS NOT NULL')
🧪 연습 문제
문제 1: 학생 성적 조회 시스템
과제: 학생 성적 데이터베이스를 만들고 다양한 조건으로 조회하세요.
요구사항:
students테이블 생성 (id, name, subject, score)- 다음 데이터 추가:
- (1, ‘홍길동’, ‘수학’, 85)
- (2, ‘홍길동’, ‘영어’, 92)
- (3, ‘김철수’, ‘수학’, 78)
- (4, ‘김철수’, ‘영어’, 88)
- (5, ‘이영희’, ‘수학’, 95)
- (6, ‘이영희’, ‘영어’, 90)
- (7, ‘박민수’, ‘수학’, 70)
- (8, ‘박민수’, ‘영어’, 75)
- 다음 쿼리 작성 및 실행:
- 수학 점수가 80점 이상인 학생
- ‘홍길동’ 학생의 모든 성적
- 과목별 평균 점수 (힌트: AVG와 GROUP BY)
- 점수 상위 3명
💡 힌트
WHERE subject = '수학' AND score >= 80WHERE name = '홍길동'SELECT subject, AVG(score) FROM students GROUP BY subjectORDER BY score DESC LIMIT 3
✅ 정답
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import sqlite3
conn = sqlite3.connect('school.db')
cursor = conn.cursor()
# 1. 테이블 생성
cursor.execute('''
CREATE TABLE IF NOT EXISTS students (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
subject TEXT NOT NULL,
score INTEGER NOT NULL
)
''')
# 2. 데이터 추가
students_data = [
(1, '홍길동', '수학', 85),
(2, '홍길동', '영어', 92),
(3, '김철수', '수학', 78),
(4, '김철수', '영어', 88),
(5, '이영희', '수학', 95),
(6, '이영희', '영어', 90),
(7, '박민수', '수학', 70),
(8, '박민수', '영어', 75)
]
cursor.executemany('INSERT OR IGNORE INTO students VALUES (?, ?, ?, ?)', students_data)
conn.commit()
# 3-1. 수학 점수 80점 이상
print("=== 수학 80점 이상 학생 ===")
cursor.execute('SELECT name, score FROM students WHERE subject = "수학" AND score >= 80')
for row in cursor.fetchall():
print(f"{row[0]}: {row[1]}점")
# 3-2. 홍길동 학생의 모든 성적
print("\n=== 홍길동 학생 성적 ===")
cursor.execute('SELECT subject, score FROM students WHERE name = "홍길동"')
for row in cursor.fetchall():
print(f"{row[0]}: {row[1]}점")
# 3-3. 과목별 평균 점수
print("\n=== 과목별 평균 점수 ===")
cursor.execute('SELECT subject, AVG(score) FROM students GROUP BY subject')
for row in cursor.fetchall():
print(f"{row[0]}: {row[1]:.1f}점")
# 3-4. 점수 상위 3명
print("\n=== 점수 상위 3명 ===")
cursor.execute('SELECT name, subject, score FROM students ORDER BY score DESC LIMIT 3')
for i, row in enumerate(cursor.fetchall(), 1):
print(f"{i}위: {row[0]} ({row[1]} {row[2]}점)")
conn.close()
출력:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
=== 수학 80점 이상 학생 ===
홍길동: 85점
이영희: 95점
=== 홍길동 학생 성적 ===
수학: 85점
영어: 92점
=== 과목별 평균 점수 ===
수학: 82.0점
영어: 86.2점
=== 점수 상위 3명 ===
1위: 이영희 (수학 95점)
2위: 홍길동 (영어 92점)
3위: 이영희 (영어 90점)
문제 2: E-commerce 상품 필터링
과제: 온라인 쇼핑몰의 상품 필터링 기능을 구현하세요.
요구사항:
shop_products테이블 생성 (id, name, category, price, rating, stock)- 최소 10개 이상의 다양한 상품 데이터 추가
- 다음 검색 기능 구현:
- 특정 카테고리 + 가격 범위로 검색
- 평점 4.0 이상 상품만 표시
- 재고가 있는 상품만 표시 (stock > 0)
- 인기순 정렬 (평점 높은 순)
- 페이징 구현 (한 페이지당 5개)
💡 힌트
WHERE category = ? AND price BETWEEN ? AND ?WHERE rating >= 4.0WHERE stock > 0ORDER BY rating DESCLIMIT 5 OFFSET ?(페이지 번호 * 5)
✅ 정답
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
import sqlite3
def create_shop():
"""쇼핑몰 데이터베이스 생성"""
conn = sqlite3.connect('ecommerce.db')
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS shop_products (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
category TEXT NOT NULL,
price REAL NOT NULL,
rating REAL,
stock INTEGER DEFAULT 0
)
''')
products = [
('노트북 Pro', '전자제품', 1500000, 4.5, 10),
('무선 마우스', '전자제품', 35000, 4.2, 50),
('기계식 키보드', '전자제품', 120000, 4.7, 30),
('27인치 모니터', '전자제품', 350000, 4.3, 15),
('USB 허브', '전자제품', 25000, 3.8, 100),
('책상', '가구', 180000, 4.4, 5),
('의자', '가구', 250000, 4.6, 8),
('책장', '가구', 120000, 4.1, 12),
('스탠드', '가구', 45000, 3.9, 20),
('쿠션', '가구', 15000, 4.0, 0),
('백팩', '패션', 89000, 4.5, 25),
('지갑', '패션', 35000, 4.2, 40)
]
cursor.executemany('''
INSERT INTO shop_products (name, category, price, rating, stock)
VALUES (?, ?, ?, ?, ?)
''', products)
conn.commit()
conn.close()
def search_products(category=None, min_price=None, max_price=None,
min_rating=None, in_stock_only=False,
page=1, per_page=5):
"""고급 상품 검색"""
conn = sqlite3.connect('ecommerce.db')
cursor = conn.cursor()
query = "SELECT * FROM shop_products WHERE 1=1"
params = []
if category:
query += " AND category = ?"
params.append(category)
if min_price is not None:
query += " AND price >= ?"
params.append(min_price)
if max_price is not None:
query += " AND price <= ?"
params.append(max_price)
if min_rating is not None:
query += " AND rating >= ?"
params.append(min_rating)
if in_stock_only:
query += " AND stock > 0"
# 정렬 및 페이징
query += " ORDER BY rating DESC"
offset = (page - 1) * per_page
query += f" LIMIT {per_page} OFFSET {offset}"
cursor.execute(query, params)
results = cursor.fetchall()
conn.close()
return results
# 실행
print("=== 데이터베이스 생성 ===")
create_shop()
# 검색 1: 전자제품, 10만원 이하
print("\n=== 전자제품 10만원 이하 ===")
results = search_products(category='전자제품', max_price=100000)
for product in results:
print(f"{product[1]}: {product[3]:,}원 (평점 {product[4]})")
# 검색 2: 평점 4.5 이상
print("\n=== 평점 4.5 이상 상품 ===")
results = search_products(min_rating=4.5)
for product in results:
print(f"{product[1]}: 평점 {product[4]} (재고 {product[5]}개)")
# 검색 3: 재고 있는 가구, 페이지 1
print("\n=== 재고 있는 가구 (1페이지) ===")
results = search_products(category='가구', in_stock_only=True, page=1, per_page=3)
for product in results:
print(f"{product[1]}: {product[3]:,}원 (재고 {product[5]}개)")
# 검색 4: 모든 상품, 인기순 TOP 5
print("\n=== 인기 상품 TOP 5 ===")
results = search_products(per_page=5)
for i, product in enumerate(results, 1):
print(f"{i}위: {product[1]} (평점 {product[4]})")
출력:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
=== 데이터베이스 생성 ===
=== 전자제품 10만원 이하 ===
무선 마우스: 35,000원 (평점 4.2)
USB 허브: 25,000원 (평점 3.8)
=== 평점 4.5 이상 상품 ===
기계식 키보드: 평점 4.7 (재고 30개)
의자: 평점 4.6 (재고 8개)
노트북 Pro: 평점 4.5 (재고 10개)
백팩: 평점 4.5 (재고 25개)
=== 재고 있는 가구 (1페이지) ===
의자: 250,000원 (재고 8개)
책상: 180,000원 (재고 5개)
책장: 120,000원 (재고 12개)
=== 인기 상품 TOP 5 ===
1위: 기계식 키보드 (평점 4.7)
2위: 의자 (평점 4.6)
3위: 노트북 Pro (평점 4.5)
4위: 백팩 (평점 4.5)
5위: 책상 (평점 4.4)
📝 오늘 배운 내용 정리
- SELECT: 데이터 조회 (* 또는 특정 컬럼)
- WHERE: 조건 필터링 (=, <>, <, >, <=, >=)
- 논리 연산자: AND, OR, NOT
- 패턴 매칭: LIKE (%, _)
- 범위/목록: BETWEEN, IN, NOT IN
- 정렬: ORDER BY (ASC/DESC)
- 제한: LIMIT, OFFSET (페이징)
- NULL 처리: IS NULL, IS NOT NULL
- 집계 함수: COUNT, SUM, AVG, MIN, MAX
🔗 관련 자료
📚 이전 학습
Day 73: SQL 기본 (CREATE, INSERT) ⭐⭐
어제는 테이블 생성과 데이터 추가 방법을 배웠습니다!
📚 다음 학습
Day 75: SQL 기본 (UPDATE, DELETE) ⭐⭐
내일은 데이터를 수정하고 삭제하는 UPDATE와 DELETE를 배웁니다!
“늦었다고 생각할 때가 가장 빠른 시기입니다!” 🚀
Day 74/100 Phase 8: 데이터베이스와 SQL #100DaysOfPython
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.
