# 일대일, 다대다 관계
## 개념
---
#### 다양한 관계들
DB속 데이터는 PK와 FK의 연결을 통해 다양한 관계를 가진다. 이들은 크게 1:N, 1:1, M:N으로 나뉜다.

#### 일대일(1:1) 관계
예를 들어, 국가와 수도는 일대일(One-to-One) 관계다. 한 국가에 여러 수도가 존재하지 않고, 거꾸로 한 수도 또한 여러 나라에 속하지 않는다. 이를 DB화 한다면, FK를 어느 테이블에 두어야 할까? 일반적으로 포함된 쪽 또는 덜 사용되는 쪽에 놓는게 좋다.

#### 다대다(M:N) 관계
다대다(Many-to-Many) 관계는 양방향에서 모두 다수로 연결될 수 있다. 쇼핑몰을 예로 들자. 고객은 다양한 상품을 주문할 수 있고, 상품 또한 다양한 고객으로부터 주문될 수 있다. 이를 DB화 하려면, 두 관계를 잇는 중간 테이블이 필요하다. 중간 테이블에는 양측을 잇기 위한 두 FK가 필요하다.

#### 인스타그램의 예
인스타그램 사용자(users)와 각 사용자별 설정(settings) 값은 1:1 관계이다. 각 설정값이 계정에 속하는 개념이므로, FK는 설정 테이블에 두는게 좋다.

인스타그램 사용자(users)와 사진(photos)은 "사진 게시"를 통해 일대다 관계이지만, "좋아요 등록"을 통해서는 다대다 관계가 된다. 한 사용자는 다양한 사진에 좋아요를 누를 수 있고, 거꾸로 하나의 사진은 다양한 유저들로부터 좋아요를 받을 수 있다.

## 실습
---
#### 테이블 생성
```
-- 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
;
```
## 훈련
---
#### 다음 테이블을 참고하여 질문에 답하시오.

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)
;
```