diff --git a/keyword/chaptor01/keyword.md b/keyword/chaptor01/keyword.md new file mode 100644 index 0000000..6f93d36 --- /dev/null +++ b/keyword/chaptor01/keyword.md @@ -0,0 +1,116 @@ +- DB Join이란? + + --- + + **두 개 이상의 테이블을 연결해서 한 번에 조회하는 것** + + 테이블은 정규화를 진행하면서 데이터가 여러 테이블에 나뉘어 저장된다. 해당 데이터를 조회할 때 여러 테이블의 데이터와 연관되어 있어 함께 조회해야 하는 경우에 사용한다. (PK↔FK 관계) + +--- + +- Join 종류들 + + --- + + 1. **INNER JOIN** : 양쪽 테이블 모두에 매칭되는 데이터만 반환 + + ex) members, reviews 테이블을 조회할 때 리뷰를 달지 않은 회원은 조회 대상에서 제외됨 + + 2. **LEFT JOIN**: 왼쪽 테이블을 기준으로 오른쪽 테이블에 매칭이 없으면 NULL을 채워 전부 조회 (WHERE 조건이 오른쪽 테이블 컬럼에 걸리면 NULL행이 전부 필터링 될 수 있음) + + ⇒ **가장 많이 사용됨**. + + 3. **RIGHT JOIN**: 오른쪽 테이블을 기준으로 왼쪽 테이블에 매칭이 없으면 NULL을 채워 전부 조회 + + ⇒ 잘 안 쓰임 (reviews 테이블에는 데이터가 있는데 members에 데이터가 없다? → 그냥 테이블 순서 바꿔서 LEFT JOIN을 사용할 수 있음!) + + 4. **FULL OUTER JOIN** : 양쪽 테이블을 모두 포함 + 매칭 없으면 NULL로 채움 + + ⇒ MySQL에서는 지원을 안함 + + --- + +--- + + +- 트랜잭션이란? + + --- + + **데이터베이스에서 여러 쿼리를 하나로 묶은 논리적인 작업 단위**로, 작업의 수행 결과가 ‘전부 성공’ or ‘전부 실패’ 2가지 케이스만 나오도록 보장한다. + + [ACID 특성] - 트랜잭션이 보장하는 특성 4가지 + + 1. **원자성 (Atomicity)** + + 트랜잭션 내에서 실행한 작업들은 마치 하나의 작업처럼 전부 성공하거나 전부 실패해야 한다. + + 하나라도 실패할 경우 **Roll back** 진행 + + 2. **일관성 (Consistency)** + + 모든 트랙잭션은 작업 전후로 데이터 무결성을 유지해야 하며, 일관성 있는 데이터베이스 상태를 유지해야 한다. + + 3. **고립성 (Isolation)** + + 동시에 진행되는 여러 트랜잭션들이 서로에게 영향을 미치지 않도록 격리한다. + + ⇒ 트랜잭션이 완료되기 전의 중간 상태를 다른 트랜잭션이 볼 수 없어야 한다. + + 4. **지속성 (Durability)** + + COMMIT이 완료된 데이터는 데이터베이스에 영구 저장되어야 한다. + + + [트랜잭션을 왜 사용할까?] + + ex) 입금 상황: 제이 → 준 (5,000원 입금 시도) + + 1. 제이 계좌 -5,000원 쿼리 A + 2. 준 계좌 +5,000원 쿼리 B + + 이때, 쿼리 A 성공 후 서버 장애 발생 시 소중한 5,000원은 공중 분해가 되는 것인가? 트랜잭션을 사용하면 쿼리 A는 Roll back이 진행되어 전부 없던 일로 된다. + + ex) 트랜잭션 A : 제이 → 준 (5,000원 송금 중 상황), + + 트랜잭션 B : 준 잔고 조회 (고립성 특성으로 인해 불가능) + + [Spring boot에서 트랜잭션 사용 과정] + + `@Transactional` 어노테이션 사용 시 자동으로 트랜잭션 적용 + + - 메서드 시작 → 트랜잭션 시작 + - 메서드 정상 종료 → 자동 COMMIT + - 메서드 예외 바생 → 자동 Roll back + + --- +--- +- Join on 과 where의 차이점 + + --- + + ON: Join할 때 두 테이블을 어떤 기준으로 연결할지 결정하는 조건 + + WHERE: Join 완료 후 결과에서 필터링하는 조건 + + [실행 순서] + + 1. FROM으로 테이블 가져옴 + 2. ON 조건으로 JOIN 수행 + 3. WHERE 조건으로 필터링 + + [LEFT JOIN + ON 조건] + + → 조건 불만족해도 왼쪽 테이블은 유지 + + → 오른쪽 테이블 NULL 채워서 가져옴 + + [LEFT JOIN + WHERE 조건] + + → NULL 행이 자동으로 필터링돼서 제외됨 + + → INNER JOIN처럼 동작함 + + ON member.member_id = reviews.member_id + + WHERE reviews.star ≥ 4 (별점 4점 이상만) \ No newline at end of file diff --git "a/mission/chaptor01/images/umc_0\354\243\274\354\260\250_erd\354\204\244\352\263\204_\354\210\230\354\240\225\353\263\270.jpg" "b/mission/chaptor01/images/umc_0\354\243\274\354\260\250_erd\354\204\244\352\263\204_\354\210\230\354\240\225\353\263\270.jpg" new file mode 100644 index 0000000..95082ee Binary files /dev/null and "b/mission/chaptor01/images/umc_0\354\243\274\354\260\250_erd\354\204\244\352\263\204_\354\210\230\354\240\225\353\263\270.jpg" differ diff --git a/mission/chaptor01/mission.md b/mission/chaptor01/mission.md new file mode 100644 index 0000000..7737d5c --- /dev/null +++ b/mission/chaptor01/mission.md @@ -0,0 +1,77 @@ +- (필수) 0주차 때 **직접 설계한** 데이터베이스를 토대로 아래의 화면에 대한 쿼리를 작성 + + + [0주차 erd 설계 수정 부분] + + - 미션 테이블 - ‘마감 날짜’ 속성 추가 + - 지역 테이블 & 지역 이름 속성 추가 + - 사용자-미션 테이블 ↔ 리뷰 테이블 연관관계 삭제 +![0주차 erd 설계 수정본](./images/umc_0주차_erd설계_수정본.jpg) + + +--- +### 1. 리뷰 작성하는 쿼리, 사진의 경우는 일단 배제 + +```sql +INSERT INTO reviews (member_id, store_id, star, content, created_at, updated_at) +VALUES (1, 2, 5, ‘음 너무 맛있어요’, NOW(), NOW()); +``` +리뷰 테이블에 [사용자 id, 가게 id, 별점, 리뷰 내용, 생성일자, 수정일자] 데이터를 넣는다. + +### 2. 내가 진행중, 진행 완료한 미션 모아서 보는 쿼리(페이징 포함) + +```sql +SELECT mm.member_mission_id, + mm.mission_status, + m.mission_condition, + m.reward_point, + s.store_id +FROM member_mission AS mm + JOIN missions AS m ON mm.mission_id = m.mission_id + JOIN stores AS s ON m.store_id = s.store_id +WHERE mm.member_id = 1 AND mm.mission_status = 'COMPLETED' +ORDER BY mm.started_at DESC + LIMIT 10 OFFSET 0; +``` +[미션 id, 미션 상태, 가게 id,미션 조건, 보상 포인트] +속성을 가져온다. 미션 테이블과 가게 테이블을 JOIN 하였고 +미션 상태가 'COMPLETED'인 것을 WHERE 조건으로 넣었다. + +### 3. 마이 페이지 화면 쿼리 + +```sql +SELECT m.nickname, + m.email, + m.phone_number, + m.point +FROM members AS m +WHERE m.member_id = 1; +``` +사용자 테이블에서 [닉네임, 이메일, 전화번호, 포인트] 데이터를 가져온다. +### 4. 홈 화면 쿼리 (현재 선택 된 지역에서 도전이 가능한 미션 목록, 페이징 포함) + +```sql +SELECT COUNT(*) +FROM member_mission AS mm + JOIN missions AS m ON m.mission_id = mm.mission_id + JOIN stores AS s ON s.store_id = m.store_id + JOIN regions AS r ON r.region_id = s.region_id +WHERE mm.member_id = 1 + AND mm.mission_status = 'COMPLETED' + AND r.region_name = '안암동'; + +SELECT s.store_name, + s.store_category, + m.mission_period, + m.mission_condition, + m.reward_point +FROM missions AS m + JOIN stores AS s ON s.store_id = m.store_id + JOIN regions AS j ON j.region_id = s.region_id +WHERE r.region_name = '안암동' +ORDER BY m.deadline ASC + LIMIT 10 OFFSET 0; +``` +‘안암동’ 기준으로 카운트 쿼리를 통해 총 미션 개수 중 COMPLETED 미션 개수를 센다. + +[가게 이름, 가게 카테고리, 보상포인트, 미션 데드라인, 미션 조건] 데이터를 가져온다. 이 쿼리 역시 ‘안암동’ 기준이며 성공 여부를 체크한다.