# 일대일, 다대다 관계
## 개념
---
#### 다양한 관계들
DB속 데이터는 PK와 FK의 연결을 통해 다양한 관계를 가진다. 이들은 크게 1:N, 1:1, M:N으로 나뉜다.
![홍팍-SQL-데이터의-관계](http://drive.google.com/thumbnail?export=view&sz=w960&id=1TJeI3O3n_NTFpueh83donv4BOTRA1vv0)
#### 일대일(1:1) 관계
예를 들어, 국가와 수도는 일대일(One-to-One) 관계다. 한 국가에 여러 수도가 존재하지 않고, 거꾸로 한 수도 또한 여러 나라에 속하지 않는다. 이를 DB화 한다면, FK를 어느 테이블에 두어야 할까? 일반적으로 포함된 쪽 또는 덜 사용되는 쪽에 놓는게 좋다.
![홍팍-sql-일대일-관계-one-to-one](http://drive.google.com/thumbnail?export=view&sz=w960&id=1TMOuRcnBPxHM4bQGy0yui8rmmU4chDZk)
#### 다대다(M:N) 관계
다대다(Many-to-Many) 관계는 양방향에서 모두 다수로 연결될 수 있다. 쇼핑몰을 예로 들자. 고객은 다양한 상품을 주문할 수 있고, 상품 또한 다양한 고객으로부터 주문될 수 있다. 이를 DB화 하려면, 두 관계를 잇는 중간 테이블이 필요하다. 중간 테이블에는 양측을 잇기 위한 두 FK가 필요하다.
![홍팍-sql-다대다-관계-many-to-many](http://drive.google.com/thumbnail?export=view&sz=w960&id=1TPLh0JNBLUAT286__igDC47ps8q8i45i)
#### 인스타그램의 예
인스타그램 사용자(users)와 각 사용자별 설정(settings) 값은 1:1 관계이다. 각 설정값이 계정에 속하는 개념이므로, FK는 설정 테이블에 두는게 좋다.
![홍팍-sql-인스타그램-일대일-관계-예](http://drive.google.com/thumbnail?export=view&sz=w960&id=1TSoM4WwhUpjalRtDq3mbja6n1vZiLkMr)
인스타그램 사용자(users)와 사진(photos)은 "사진 게시"를 통해 일대다 관계이지만, "좋아요 등록"을 통해서는 다대다 관계가 된다. 한 사용자는 다양한 사진에 좋아요를 누를 수 있고, 거꾸로 하나의 사진은 다양한 유저들로부터 좋아요를 받을 수 있다.
![홍팍-sql-다대다-관계-many-to-many-인스타그램-예](http://drive.google.com/thumbnail?export=view&sz=w960&id=1TVAoBHAjrI2_7FFWm8cBGuqeShIdsXY_)
## 실습
---
#### 테이블 생성
```
-- settings 테이블 생성
CREATE TABLE settings (
id SERIAL PRIMARY KEY, -- PK
private BOOLEAN, -- true/false
adding_photos VARCHAR(15), -- AUTO, MANUAL
user_id INTEGER UNIQUE REFERENCES users(id) -- FK: 개인설정 유저(1:1 연결)
);
-- likes 테이블 생성(사용자와 사진을 다대다 연결)
CREATE TABLE likes (
id SERIAL PRIMARY KEY, -- PK
user_id INTEGER REFERENCES users(id), -- FK: 좋아요를 누른 사람(1:N 연결)
photo_id INTEGER REFERENCES photos(id) -- FK: 좋아요된 사진(1:N 연결)
);
```
#### 레코드 생성
```
-- settings 레코드 생성
INSERT INTO
settings(private, adding_photos, user_id)
VALUES
(FALSE, 'MANUAL', 1), -- 유저#1
(FALSE, 'AUTO', 2), -- 유저#2
(TRUE, 'AUTO', 3) -- 유저#3
;
-- likes 레코드 생성
INSERT INTO
likes(user_id, photo_id)
VALUES
-- 사진#1에 달린 좋아요
(1, 1), -- 유저#1
(2, 1), -- 유저#2
-- 사진#2에 달린 좋아요
(1, 2), -- 유저#1
(2, 2), -- 유저#2
(3, 2), -- 유저#3
-- 사진#3에 달린 좋아요
(1, 3), -- 유저#1
(3, 3) -- 유저#3
;
```
## 훈련
---
#### 다음 테이블을 참고하여 질문에 답하시오.
![홍팍-SQL-입문-데이터의-관계-일대일-다대다-좋아요-문제](http://drive.google.com/thumbnail?export=view&sz=w960&id=1Smd2Gpq39OHBQPLQ5Xa8GhDtezFMAHE9)
1. 좋아요가 가장 많이 달린 사진은 무엇?
2. 좋아요가 가장 적은 사진은 무엇?
3. 좋아요를 가장 많이 누른 사용자는, 공개 계정으로 설정돼있는가?
4. 다음 쿼리의 수행을 막으려면, FK인 user_id 컬럼에 어떤 조건을 주어야 하는가?
```
INSERT INTO
settings(private, adding_photos, user_id)
VALUES
(FALSE, 'AUTO', 3),
(FALSE, 'AUTO', 3),
(FALSE, 'AUTO', 3)
;
```
5. 다음 쿼리가 의미하는 바는 무엇?
```
INSERT INTO
likes(user_id, photo_id)
VALUES
(1, 1),
(1, 1),
(1, 1),
(1, 1)
;
```