내용
- join 의미
- implicit join vs explicit join
- inner join vs outer join
- left outer join
- right outer join
- full outer join
- equi join
- natural join
- cross join
우선 시작하기에 앞서 내용 이해에 필요한 테이블 구조를 사진으로 보여드리겠습니다.
테이블 구조
ID가 1인 임직원이 속한 부서 이름을 조회하는 쿼리를 짜봅시다.
EMPLOYEE, DEPARTMENT
ID가 1인 임직원이 속한 부서 이름은?
SELECT D.name
FROM employee AS E, department AS D
WHERE E.id = 1 and E.dept_id = D.id;
쿼리를 짠다면 위처럼 조건 'id가 1인 직원'과 그 직원의 부서 ID와 Department id가 동일한 Department tuble을 조회하고 그 이름을 결과로 보여줍니다.
위 사진의 경우에는 Department id가 1003인 DEV가 출력됩니다.
implicit join: from절에는 table들만 나열하고 where절에 join condition을 명시하는 방식
위의 예시처럼 여러 에러 사항 때문에 이후에 SQL 표준에 조인을 명시할 수 있는 문법이 추가가 됩니다.
그것이 바로 explicit join 입니다.
위의 쿼리를 explicit join을 사용해서 변경
SELECT D.name
FROM employee AS E JOIN department AS D ON E.dept_id = D.id
WHERE E.id = 1
explicit join: from절에 JOIN 키워드와 함께 joined table들을 명시하는 방식
inner join, outer join을 들어본적 있으신가요? 앞으로의 설명의 이해를 위해서 아래의 사진을 참고해주세요!
우선 다음과 같은 쿼리가 있다고 하겠습니다.
SELECT *
FROM employee E JOIN department D ON E.dept_id = D.id;
사실 JOIN이라는 키워드 앞에는 INNER가 생략되어 있는 상태입니다. 때문에 생략하지 않고 모두 적어주면 다음과 같은 쿼리가 됩니다.
SELECT *
FROM employee E INNER JOIN department D ON E.dept_id = D.id;
그렇다면 inner join은 어떻게 동작하는 걸까요?
다음과 같은 테이블이 있다고 하겠습니다.
employee 테이블 먼저 살펴봅시다. SIMON을 주목해보겠습니다. SIMON은 dept_id가 NULL입니다. 또한 DEPARTMENT 테이블의 id가 1002인 테이블도 leader_id가 NULL입니다.
SELECT *
FROM employee E INNER JOIN department D ON E.dept_id = D.id;
이 경우 이 쿼리를 실행하면 어떻게 될까요? EMPLOYEE 테이블의 dept_id와 DEPARTMENT 테이블의 leader_id가 같은 튜플을 연결하고 결과로 보여줄 것입니다.
이때 의문이 있습니다. SIMON과 DEPARTMENT 테이블의 id가 1002인 테이블은 각각의 값이 NULL입니다. 결과로는 어떻게 표현될까요?
결과
매칭이 안된 두 튜플은 출력에서 사라집니다.
이제 inner join은 아래 처럼 정리할 수 있습니다.
innet join: 두 table에서 join condition을 만족하는 tuple들로 result table을 만드는 join
FROM table1 [INNER] JOIN table2 ON join_condition
outer join: 두 table에서 join condition을 만족하지 않는 tuple들도 result table에 포함하는 join
FROM table1 LEFT [OUTER] JOIN table2 ON join_condition
FROM table1 RIGHT [OUTER] JOIN table2 ON join_condition
FROM table1 FULL [OUTER] JOIN table2 ON join_condition
앞의 inner 조인에서 사용했던 쿼리를 LEFT OUTER JOIN으로 변경해서 실행해보겠습니다.
LEFT OUTER JOIN 사용
SELECT *
FROM employee E LEFT OUTER JOIN department D ON E.dept_id = D.id;
위 사진의 경우에서 쿼리를 실행한다면 어떤 결과가 나올까요? inner join에서는 NULL 값을 가진 두 튜플을 제외했었습니다. outer left join에서의 결과를 예상해봅시다.
위에서 설명했듯이 outer join은 join condition을 만족하지 않는 tuple들도 result table에 포함합니다.
따라서 위 사진처럼 SIMON이 결과에 포함이 됩니다. 하지만 outer left join이기 때문에 left에 위치한 employee 테이블의 결과만 return 되고 department table의 정보는 여전히 누락되어 있습니다.
이번에는 FULL OUTER JOIN을 해보겠습니다.
FULL OUTER JOIN 사용
pgrsql# SELECT *
FROM employee E FULL OUTER JOIN department D ON E.dept_id = D.id;
pgrsql#을 붙여준 것은 mysql은 full outer join을 지원하지 않기 때문에 pgrsql에서 실행을 했습니다!
쿼리를 실행한 결과가 예상이 가시나요?
결과는 예상대로 NULL은 가진 두 개의 정보 모두 결과에 포함이 되어서 출력됩니다.
단적인 예로 앞에서 사용했던 쿼리들을 보겠습니다.
SELECT *
FROM employee E INNER JOIN department D ON E.dept_id = D.id;
SELECT *
FROM employee E LEFT OUTER JOIN department D ON E.dept_id = D.id;
pgrsql# SELECT *
FROM employee E FULL OUTER JOIN department D ON E.dept_id = D.id;
위 3개의 쿼리들은 모두 '='을 사용하고 있습니다. 때문에 inner join이면서 equi join이고, outer join이면서 equi join입니다.
equi join에 대한 두 가지 시각
equi join을 보는 시각은 2가지가 있습니다. 저는 앞으로 첫번째 시각을 가지고 진행을 하겠습니다.
FROM table1 NATURAL [INNER] JOIN table2
FROM table1 NATURAL LEFT [OUTER] JOIN table2
FROM table1 NATURAL RIGHT [OUTER] JOIN table2
FROM table1 NATURAL FULL [OUTER] JOIN table2
예시 테이블 구조
위의 테이블 구조를 예시로 들겠습니다.
이 경우 아래의 쿼리를 실행하면 어떤 결과가 나올까요?
SELEFT *
FROM employee E NATURAL INNER JOIN department D;
NATUAL join은 같은 이름을 가지는 attribute pair에 대해서 equi join을 수행하며, inner join은 null 값을 가지는 tuple은 result table에 포함되지 못합니다.
결과는 위처럼 나옵니다. 중복되는 attribute인 dept_id는 하나로 합쳐지고 나머지는 inner join 규칙에 따라서 결과가 만들어집니다.
위 사진의 테이블 구조를 예시로 설명하겠습니다.
CROSS JOIN 사용
SELECT *
FROM employee CROSS JOIN department;
위의 쿼리를 실행했을 때의 결과가 예상이 가시나요?
cross join은 tuple pair로 만들 수 있는 모든 조합을 result table로 반환합니다. 그렇다면 employee의 튜플 6개, department의 튜플 5개로 만들 수 있는 모든 조합인 30개의 조합이 결과로 나옵니다.
위 사진은 쿼리를 실행했을 때의 결과입니다.
cross join @MySQL
- MySQL에서는 cross join = inner join = join 이다
- CROSS JOIN에 ON(or USING)을 같이 쓰면 inner join으로 동작한다.
- INNER JOIN(or JOIN)이 ON(or USING) 없이 사용되면 cross join으로 동작한다.
JPQL의 JOIN에 대해 궁금하다면 아래의 글을 참고해주세요!
JPQL의 JOIN 설명
출처
글에 사용된 내용 및 사진은 모두 아래 영상의 자료입니다.
유튜브-쉬운코드
시니어 백엔드 개발자가 알려주는 데이터베이스 개론 & SQL