데이터들은 하나의 테이블에 모두 저장되는게 아니라, 데이터의 성격에 따라 여러 테이블에 나뉘어서 저장된다. 데이터의 성격에 따라 다른 테이블에 나뉘어 저장된다 해도, 테이블끼리 서로 유기적으로 연관되어 있는 경우가 대부분이다.
테이블별로 분리되어 있는 데이터들을 연결해서 하나의 셋으로 출력해야 할 때 쓰는 구문이 Join
이다.
만약 주문 테이블과 리뷰 테이블이 있다고 가정해보자.
주문내역에는 존재하지만, 리뷰를 작성하지 않아서 리뷰테이블에는 없는 데이터가 있을 수 있다.
이 때 주문 테이블과 리뷰 테이블을 Join하여 데이터를 조회할 때 리뷰가 없는 주문건도 조회를 할지, 아니면 리뷰가 작성된 주문건만 조회할 지 선택해야 한다.
join에는 여러 종류가 있는데, 출력하고자 하는 형식에 따라 join 종류 중 필요한 join 구문을 사용해야 한다.
- inner join
inner join은 교집합 연산과 같다. 조회하려는 컬럼이 조인하려는 테이블 모두에 공통적으로 존재하는 데이터만 조인하여 출력한다.
20개의 주문건수가 존재하는 주문테이블과, 12개의 리뷰내역이 존재하는 테이블 두 개를 inner join 으로 조회하는 구문은 이렇다.
select o.order_state, o.order_price, r.review_content, r.review_score as 점수 from my_order o
left outer join my_review r
on o.order_id = r.order_id;
20행의 주문테이블과, 12행의 리뷰테이블을 left join 으로 묶어서 조회한 결과 리뷰내역이 존재하는 12개의 행들만 조회가 된다.
만약 여기서 리뷰가 쓰여지지 않은 주문내역도 같이 조회를 하고싶으면 어떻게 할까?
inner 를 left outer로 바꿔주면 된다.
left outer join
left outer join의 용도로 생각해볼 수 있는 것 중 하나는 다음과 같다.
만약 상품을 정렬하는 기능 중 '리뷰많은순' 으로 정렬을 해야한다고 가정해보자. 그 중 어제 등록된 상품은 아직 주문이 들어오지 않아 리뷰개수가 0일 것이다.
하지만 리뷰많은순 정렬을 클릭했을 때는 리뷰개수가 0인 상품들도 나와야 한다. 등록된 리뷰가 없다고 상품 목록에서 제외를 시키는것은 안되는데, 만약 이때 inner join을 이용하여 상품 목록을 보여주게 된다면 리뷰개수가 0인 상품들은 조회가 되지 않을것이다.
이때 사용하는 조인이 left outer join이다.
위에 사진은 inner join 으로 12개의 행이 조회되는 것을 볼 수 있다.
select count(*) from my_order as o
left outer join my_review r
on o.order_id = r.order_id;
이렇게 left outer 조인으로 바꿔주게 된다면 count 컬럼의 값은 inner join의 결과로 집계됐던 12행이 아닌 20행일 것이다. 리뷰가 0개인 것들도 조회를 해주는 것이다.
더 추가적으로 설명하자면 left outer join은 왼쪽에 오는 행이 기준
이 된다.
위의 코드로 설명해보면 주문 테이블을 기준으로 리뷰 테이블을 조인한다. 조회 결과는 기준이 되는 왼쪽테이블의 모든 행과 오른쪽 테이블의 매칭되는 행을 조인하게되는데, 만약 오른쪽 테이블에서 매칭되는 행이 없으면 NULL 값이 반환된다.
left outer join과 반대되는 right outer join
은, 오른쪽 컬럼이 기준컬럼이 되어 오른쪽 테이블의 모든 행과 왼쪽 테이블의 매칭되는 행을 조인하게 된다.
Full outer join
full outer join은 기준이 되는 테이블이 없다. 상품테이블과 리뷰테이블을 조인하여 조회할 때 서로 매칭되는 값이 없어도 모두 출력해주는 합집합
과 비슷하다. A테이블에만 존재하는 행 + B테이블에만 존재하는 행 + A,B 에 모두 존재하는 행(교집합)을 모두 출력할 때 full outer join을 사용한다.(모든 행이 조건에 관계없이 결합)
현재 사용중인 mariaDB는 Full outer join을 지원하지 않는다. mariaDB에서 full outer join을 사용하려면 union
을 이용하여 조회해야 한다.
select pro_name, pro_price, review_content, review_score from my_products as p
left outer join my_review r
on p.pro_id = r.pro_id
union
select pro_name, pro_price, review_content, review_score from my_products as p
right outer join my_review r
on p.pro_id = r.pro_id;
full outer join은 결국 left outer join과 right outer join을 합친 것이기 때문에 두 조인 구문을 union을 이용해서 합쳐주면 결합한 모든 행들이 조회가 된다.