반응형
💾 비정규형 테이블 (Non-Normalized Table)
-- 비정규형 주문 테이블 (ProductList에 다중값 저장)
CREATE TABLE orders_raw (
order_id VARCHAR(10),
customer VARCHAR(100),
product_list VARCHAR(255), -- 쉼표로 묶은 다중 값
total_price INT
);
INSERT INTO orders_raw VALUES ('001', 'Alice', 'TV,Phone', 1500);
INSERT INTO orders_raw VALUES ('002', 'Bob', 'Laptop', 1000);
❌ 문제점
- product_list 컬럼에 쉼표로 구분된 다중 값이 들어 있음
- 제품 하나하나에 대한 정보가 분리되어 있지 않아서 분석이나 검색이 어려움
- 수정, 삭제, 추가 시 데이터 이상(Anomaly)이 발생할 가능성 큼
🥇 1정규형 (1NF) - 원자값으로 분리
테이블의 모든 컬럼은 더 이상 쪼갤 수 없는 단일 값(Atomic Value)만 포함해야 합니다.
-- 1NF: 하나의 제품 단위로 분해
CREATE TABLE orders_1nf (
order_id VARCHAR(10),
customer VARCHAR(100),
product VARCHAR(100),
total_price INT
);
INSERT INTO orders_1nf VALUES ('001', 'Alice', 'TV', 1500);
INSERT INTO orders_1nf VALUES ('001', 'Alice', 'Phone', 1500);
INSERT INTO orders_1nf VALUES ('002', 'Bob', 'Laptop', 1000);
🧠 설명
- 제품을 개별 행으로 분리
- 이렇게 하면 특정 제품에 대한 주문을 쉽게 조회하거나 통계 내기도 쉬워져요.
🥈 2정규형 (2NF) - 부분 종속 제거
복합키가 있는 테이블에서, 기본키 일부에만 의존하는 컬럼을 분리합니다.
-- 주문 테이블 (기본 정보만)
CREATE TABLE orders (
order_id VARCHAR(10) PRIMARY KEY,
customer VARCHAR(100),
total_price INT
);
-- 주문 상세 테이블 (제품 단위)
CREATE TABLE order_products (
order_id VARCHAR(10),
product VARCHAR(100),
PRIMARY KEY (order_id, product),
FOREIGN KEY (order_id) REFERENCES orders(order_id)
);
-- 데이터 삽입
INSERT INTO orders VALUES ('001', 'Alice', 1500);
INSERT INTO orders VALUES ('002', 'Bob', 1000);
INSERT INTO order_products VALUES ('001', 'TV');
INSERT INTO order_products VALUES ('001', 'Phone');
INSERT INTO order_products VALUES ('002', 'Laptop');
❗ 문제
- total_price는 실제로 order_id에만 종속되는 값이에요.
- 그런데 현재는 order_id + product라는 복합키에 total_price가 연결되어 있어서 중복 저장되고 있어요.
🧠 설명
- total_price는 주문 전체에 대한 정보니까 주문 기본 테이블에!
- 제품은 제품대로 order_products에 저장하면 중복 제거 성공!
✅ 3정규형 (3NF) - 이행 종속 제거
기본키가 아닌 컬럼이 다른 일반 컬럼에 종속되면, 별도로 분리해야 합니다.
-- 예시: 지역정보가 고객명에 따라 결정됨 (이행 종속)
-- orders 테이블에 다음처럼 저장된다고 가정
+----------+-----------+-------------+---------+
| OrderID | Customer | TotalPrice | Region |
+----------+-----------+-------------+---------+
| 001 | Alice | 1500 | Seoul |
| 002 | Bob | 1000 | Busan |
- Region은 사실상 Customer에 종속된 정보예요.
- 고객의 지역이 자주 바뀌는 경우, 여러 행을 동시에 수정해야 해서 갱신 이상이 발생할 수 있어요.
-- 고객 테이블로 분리 (Region은 Customer에 종속되므로)
CREATE TABLE customers (
customer VARCHAR(100) PRIMARY KEY,
region VARCHAR(100)
);
-- orders 테이블은 customer만 참조하도록 유지
-- (이미 생성되어 있으면 ALTER로 FK 설정해도 OK)
-- 고객 데이터 삽입
INSERT INTO customers VALUES ('Alice', 'Seoul');
INSERT INTO customers VALUES ('Bob', 'Busan');
🧠 설명
- 고객 정보를 별도 테이블로 분리하여 데이터 중복 제거 + 관리 효율성 향상!
🧪 실습 쿼리 예시
-- 주문자별 주문 총액 확인
SELECT o.customer, o.total_price
FROM orders o;
-- 주문별 주문한 제품 확인
SELECT op.order_id, op.product
FROM order_products op;
-- 고객 지역 포함 전체 조회
SELECT o.order_id, o.customer, c.region, o.total_price
FROM orders o
JOIN customers c ON o.customer = c.customer;
🎯 요약
정규형 | 핵심 변경 내용 | 대표 테이블 구조 |
1NF | 다중값 분리 (쉼표 → 행 분리) | orders_1nf |
2NF | 주문정보 / 제품정보 분리 | orders, order_products |
3NF | 고객의 지역정보 분리 | customers (Customer → Region 종속) |
반응형
'자격증 > SQLD' 카테고리의 다른 글
ROW_NUMBER() 함수 완벽 정복 (0) | 2025.05.19 |
---|---|
단일행 함수 vs 다중행 함수 쉽게 이해하기 (0) | 2025.05.17 |
윈도우 함수 완전정복 : 순위 / 집계 / 행순서 / 비율 함수 (0) | 2025.05.12 |
ROLLUP / CUBE / GROUPING SETS / GROUPING 완전정복 (0) | 2025.05.12 |
SQL 집합 연산자 완벽 가이드: UNION / UNION ALL / INTERSECT / MINUS(EXCEPT) (0) | 2025.05.12 |