목표
Spring을 이용하면서 SQL 최적화를 위해 Join을 꽤 사용했지만, 어떤 원리로 동작하는지는 제대로 이해하지않고 그냥 이렇게 하면 Join이 된다. 라는 안일한 생각으로 SQL을 작성했던 것 같아 이번 기회에 Join에 대해 정리해보고자 한다. 여러 Join 전략 중 가장 많이 사용하는 4가지 Join 전략에 대해 이해해보자.
SQL Join이란
두 개 이상의 테이블을 서로 연결하여 데이터를 검색할 때 사용하는 방법이다. 분리되어 있는 여러 테이블을 사용자가 원하는 형식으로 조합해야할때 SQL Join문을 이용해 해결할 수 있다. Join은 아래와 같이 7개의 형식으로 사용할 수 있다.
Join의 종류와 활용 방법
오늘은 위 7개 형식의 Join 중 대부분의 Join에서 사용되는 아래 4가지 Join형식을 알아보도록 하겠다. LEFT, RIGHT, INNER, OUTER 형식이 있고, 차례대로 살펴보자.
✅ Left Outer Join & Right Outer Join
Left Outer Join은 이름 그대로 왼쪽에 있는 테이블을 기준으로 Join 테이블에 일치하는 레코드가 없더라도 왼쪽 테이블의 모든 레코드를 출력하는 Join 전략이다. 왼쪽 테이블에 Join 테이블의 레코드와 일치하는 레코드가 없다면 결과 테이블에 NULL값을 삽입한다. 예시로, 아래 두개의 테이블이 있다고 해보자.
위 두 테이블 중 USER 테이블이 왼쪽에 있다고 생각할때 Left Join의 결과는 아래와 같다. 왼족 테이블의 모든 레코드가 출력되었고 값이 비어있는 부분은 NULL로 채워 결과 테이블이 완성되었다.
위 과정을 SQL로 작성해보면 아래와 같다. 코드를 보면 FROM에 USER 테이블이 들어가있는데 즉, Left Join에서 FROM절에 들어가 있는 테이블이 기준 테이블이 되는 것이다.
SELECT *
FROM USER U
LEFT JOIN ORDER O
ON U.user_id = O.user_id;
그럼 USER 테이블과 ORDER 테이블의 위치를 바꿔서 실행하면 어떻게 될까? 아래와 같이 SQL을 작성했을때 결과 테이블은 아래와 같다. USER 테이블과 Join된 ORDER 테이블의 모든 레코드가 출력된다.
SELECT *
FROM ORDER O
LEFT JOIN USER U
ON O.user_id = U.user_id
위 결과에서는 ORDER 테이블을 기준으로 Left Join을 진행하였는데 이 결과는 USER 테이블을 기준으로 Right Join을 한 Column의 순서만 다를 뿐 레코드의 결과는 동일하다.
Left Join과 Right Join을 묶어서 설명한 이유가 여기에 있다. Left Join을 이용하더라도 기준이되는 FROM 절에 어떤 테이블이 들어가냐에따라 Left Join이 될 수도 있고 Right Join이 될 수 있다. 처음에는 Left, Right Join 개념에 대해 헷갈렸는데 Left, Rigth 라는 이름때문에 헷갈렸던 것 같다. 어떤 방향의 Join을 사용하더라도 그 기준이 되는 테이블을 잘 설정하고 Join할 수 있다면 해당 개념이 매우 쉬워질 것이라고 생각한다.
✅ Inner Join
Inner Join은 포스트 초반 보여준 그림처럼 두개의 테이블에서 연결 가능한 레코드만 연결하여 결과 테이블을 만들어내는 Join 전략이다. 이전에 설명한 Left Join에서 NULL 값을 가지는 레코드를 볼 수 있었는데 그런 NULL값을 가진 레코드를 제외한 결과 테이블을 만들어내는 것이 Inner Join이라고 생각하면 쉽다. 아래와 같이 SQL을 작성했을때 결과는 아래와 같다.
SELECT *
FROM USER U
INNER JOIN ORDERS O
ON U.user_id = O.user_id;
✅ Full Outer Join
Full Outer Join은 두 개의 테이블이 가지고 있는 모든 레코드를 Join해서 출력하는 전략이다. 앞서 보았던 Join 전략들과 달리 연결 가능하지 않더라도 양방향으로 NULL 값을 포함해 모든 레코드를 출력한다. 아쉽게도 MySQL엔진 기반의 문법은 Full Outer Join 이라는 문법을 지원하지 않는다. 따라서, Left, Right Join과 Union을 이용해 아래와 같이 SQL을 작성해 구현한다.
SELECT *
FROM USER U
LEFT JOIN ORDERS O
ON U.user_id = O.user_id
UNION
SELECT *
FROM USER U
RIGHT JOIN ORDERS O
ON U.user_id = O.user_id
본 예제에서는 ORDER 레코드는 user_id를 필수적으로 가지고 있어야하기 때문에 Full Outer Join을 적절하기 설명하기 어렵지만, 억지로 user_id 4를 가지는 ORDER 레코드를 하나 만들어 Full Outer Join을 해보면 아래와 같다. 두 개의 테이블에서 가지는 레코드가 모두 출력된 것을 볼 수 있고 다른 테이블과 연결되는 레코드가 존재하지 않는다면 양방향으로 NULL 값을 넣어 결과 테이블을 만들어내는 것을 볼 수 있다.
[ 참고자료 ]
https://makand.tistory.com/entry/SQL-LEFT-JOIN-%EA%B5%AC%EB%AC%B8