[DB] 8. Join

편준민's avatar
Feb 26, 2025
[DB] 8. Join
💡
Join (조인)
  1. 테이블의 연관 관계를 우선 파악
      • 일대일, 일대다, 다대다 관계
      • 외래 키 및 제약 조건 설정
  1. Inner Join vs Outer Join
    1. Inner Join : 서로 일치하는(존재하는) 데이터만 출력
    2. Outer Join : 한 쪽은 무조건 다 뿌리고, 나머지는 없으면 null로 출력
      1. Left, Right는 어느 테이블을 Driving으로 정하는 지에 따라 다름
 

0. Join이란?

  • Join : 두 테이블을 각각 조회하는 것이 아닌(두 번의 select), 두 테이블을 합친 것처럼 한 번의 조회로 두 곳의 데이터를 한 번에 찾는 방법
    • 두 테이블 간의 연관 관계를 잘 파악하는 것이 제일 중요
    • 일대일 관계, 일대다 관계, 다대다 관계가 존재
 

연관 관계

  • 두 테이블 간 데이터의 관계
  • ex 1) 인스타그램 (Instagram) : 유저 - 피드
    • 유저는 피드를 여러 개 작성 가능 (N)
    • 피드한 사람에 의해서만 작성될 수 있음 (1)
      • 즉, 유저와 피드의 관계는 1 : N (일대다) 관계
      • 참조하는 쪽이 외래 키를 가지고 있어야 검색 속도가 빠름 (Random Access)
      • 즉, 피드 측에서 유저 테이블을 참조 : 피드 테이블에 외래 키 필요
        • 이때, 외래 키 = 유저 테이블의 기본 키
notion image
  • 인스타그램 : 피드 - 댓글
    • 피드에는 여러 개의 댓글이 달릴 수 있음 (N)
    • 댓글은 작성되면 하나의 피드에만 작성됨 (1)
      • 즉, 피드와 댓글의 관계는 1 : N (일대다) 관계
      • 댓글 측에서 피드 테이블을 참조 : 댓글 테이블에 외래 키 필요
        • 이때, 외래 키 = 피드 테이블의 기본 키
notion image
  • 인스타그램 : 유저 - 댓글
    • 유저여러 개의 댓글을 작성할 수 있음 (N)
    • 하나의 댓글한 명의 유저에게만 작성됨 (1)
      • 즉, 유저와 댓글의 관계는 1 : N (일대다) 관계
      • 댓글 측에서 유저 테이블을 참조 : 댓글 테이블에 외래 키 필요
        • 이때, 외래 키 = 유저 테이블의 기본 키
notion image
  • ex 2) 쇼핑몰
    • 유저상품을 여러 종류 구매 가능 (N)
    • 상품여러 유저들에게 구매될 수 있음 (N)
      • 이 경우, 유저와 상품은 N : M (다대다) 관계
        • 두 테이블이 명사일 경우, 동사 테이블이 무조건 만들어짐
        • 위의 경우, ‘유저’가 ‘상품’을 ‘구매’하므로 ‘구매’ 테이블 생성
        • ‘구매’의 행위에는 트랜잭션의 파악이 중요
 
유저가 쇼핑몰에서 물품을 구매할 때의 트랜잭션(Transaction)
  1. 가입된 유저가 물품 구매를 요청
      • 서버에서는 유저가 구매 요청한 물품의 재고를 확인
        • 재고가 충분한지 확인해야 함
        • 재고가 없다면, 서버 측에서 구매 테이블에 데이터를 추가하지 말고, 에러 반환
          • 이를 유효성 검사라고 함
  1. 재고 계산 (주문 처리)
    1. 현재 구매하려는 물품의 재고를 변수에 받아와서 임시 저장 (temp = 50)
    2. 유저가 구매하려는 물품의 개수를 변수와 계산 (temp - 3)
    3. 계산되어 나온 값을 상품 테이블에 Update
        • 계산한 값을 테이블에 연산으로 적용할 시, 데이터의 일관성이 깨질 수 있음
notion image
테이블을 만들 때 유의할 점
  1. 오브젝트 파악
      • 사용자의 시나리오를 상상하면서 따라가기
        • 비즈니스 파악이 우선시
  1. 비즈니스 파악 후 연관 관계 설정
notion image
  • 인스타그램으로 보는 연관 관계
    • 유저가 피드를 작성하면, 다른 유저들이 피드에 댓글 작성 가능
      • 유저여러 피드를 올릴 수 있고, 피드에는 여러 댓글이 달릴 수 있음
      • 피드에는 댓글이 없을 수도 (null) 있음 : Outer Join
        • 피드는 다 불러오되, 댓글은 없으면 null로 처리
    • 피드에는 사진, 제목 외에 작성자의 정보가 필요
      • 작성자 id (외래 키), 작성자 이름 (username)
    • 댓글에는 댓글 내용, 댓글 작성자 정보, 피드 정보가 필요
      • 피드 id (외래 키), 댓글 작성자 id (외래 키), 댓글 작성자 이름 (username)
    • 한 번의 Select여러 테이블의 정보를 한 번에 찾으려면?
      • 피드 작성자와 유저, 댓글 작성자와 유저의 정보가 모두 동일한 데이터만 불러옴
        • = Inner Join
 
Q. 왜 Join을 사용해야 하나요? 하나의 테이블에 모든 데이터를 다 담으면 안되나요?
A : 이 역시 프로그램의 사용 목적에 따라 다릅니다. 일반적으로 데이터가 중복될 경우, 데이터를 수정하는 데에 연산 시간이 오래 소요되지만, 수정을 거의 하지 않고 Select만 많이 하게 되는 프로그램의 경우에는 하나의 테이블에서만 데이터를 읽어 오는 게 더욱 빠르므로, 데이터를 중복해서 넣는 경우 또한 존재합니다.
notion image

Data Setting

  • 테이블 생성, 더미데이터 삽입
-- Join -- 1. 테이블 생성 CREATE TABLE user_tb( id int primary key auto_increment, username varchar(20), password varchar(20), email varchar(100) ); CREATE TABLE feed_tb( id int primary key auto_increment, title varchar(1000), photo_url varchar(100), user_id int ); CREATE TABLE reply_tb( id int primary key auto_increment, content varchar(100), user_id int, feed_id int ); -- 2. 더미데이터 삽입 insert into user_tb(username, password, email) values('ssar', '1234', 'ssar@nate.com'); insert into user_tb(username, password, email) values('cos', '1234', 'cos@nate.com'); insert into user_tb(username, password, email) values('love', '1234', 'love@nate.com'); insert into feed_tb(title, photo_url, user_id) values('계곡왔어요', 'http://xn--989a5b.com', 1); insert into feed_tb(title, photo_url, user_id) values('바다왔어요', 'http://xn--2j1b67o.com', 2); insert into reply_tb(content, user_id, feed_id) values('굿', 2, 1); insert into reply_tb(content, user_id, feed_id) values('별로', 3, 1);
  • user_tb
notion image
  • feed_tb
notion image
  • reply_tb
notion image

1. Inner Join

  • 참조하는 값같은 데이터만 출력
-- 3. Join -- 1) Inner Join select * from feed_tb ft inner join user_tb ut on ft.user_id = ut.id;
notion image
결과
notion image
 
-- 2) Inner Join 2 select * from emp; select * from dept; select * from emp e inner join dept d on e.deptno = d.deptno;
notion image
결과
notion image
 
-- 3) Inner Join (Failure) select * from feed_tb ft inner join user_tb ut on ft.user_id = ut.id inner join reply_tb rt on ft.id = rt.feed_id;
결과
notion image

2. Outer Join

  • 한 쪽의 데이터를 전부 출력하고, 참조하는 데이터가 없으면 null로 표시
  • Left Outer Join : 데이터를 전부 출력할 테이블이 왼쪽에 있음
  • Right Outer Join : 데이터를 전부 출력할 테이블이 오른쪽에 있음
-- 4) Outer Join select * from feed_tb ft inner join user_tb ut on ft.user_id = ut.id left outer join reply_tb rt on ft.id = rt.feed_id;
notion image
 

3. 데이터 완성

-- 5) 데이터 완성 (Inline View) select post.feed_title, post.feed_picture, post.feed_writer, post.reply_content, rut.username reply_writer from ( select ft.title feed_title, ft.photo_url feed_picture, ut.username feed_writer, rt.content reply_content, rt.user_id reply_writer_id from feed_tb ft inner join user_tb ut on ft.user_id = ut.id left outer join reply_tb rt on ft.id = rt.feed_id ) post left outer join user_tb rut on post.reply_writer_id = rut.id; -- 5) 데이터 완성 select ft.title feed_title, ft.photo_url feed_picture, ut.username feed_writer, rt.content reply_content, rut.username reply_writer from feed_tb ft inner join user_tb ut on ft.user_id = ut.id left outer join reply_tb rt on ft.id = rt.feed_id left outer join user_tb rut on rt.user_id = rut.id -- 정렬 추가 order by ft.id, rt.id;
notion image
 

Self Join

  • 계층 구조를 표현할 때에 주로 사용
  • 가져오는 테이블들이 동일하기 때문에 별칭이 필수 (column 구별)
-- 6) Self Join select e1.empno '사원번호', e1.ename '사원명', e2.ename '상사' from emp e1 left outer join emp e2 on e1.mgr = e2.empno;
notion image
 
Share article

YunSeolAn