DB에서 정보는 종종 여러 테이블에 나눠 저장된다. 이러한 구조에서는 단일 테이블만으로는 필요한 데이터를 모두 얻기 어려울 수 있다. 이 때 Join 이라는 SQL 문법이 이를 해결해 줄 수 있는 중요한 역할을 하고, 가장 많이 사용되는 문법이라고 할 수 있다.
Join을 사용하면 여러 데이터 소스로부터 관련된 정보들을 쉽게 조회할 수 있고, 이를 통해 데이터 분석, 비즈니스 인사이트 도출을 위해 적극적으로 활용될 수 있다.
Join은 많은 유형이 있고, 각 유형은 어떻게 사용될 수 있는지 알아보고자 한다.
우선 Join 이란 두 개 혹은 그 이상의 테이블들을 공통 필드를 가지고 Merge 하는데 사용된다.
이는 Star Schema로 구성된 테이블들로 분산되어 있는 정보들을 통합하는데 활용할 수 있다.
이러한 Join은 다양한 유형이 존재하고, 각 유형별로 원하는 결과를 각각 다르게 얻을 수 있다.
다음은 Join의 유형을 나타낸 그림으로, 수학시간에 보던 집합과 비슷하게 생각하면 쉽게 와닿을거다.
보는 것 처럼 다양한 유형의 Join이 존재하며 Left Table 과 Right Table 을 조합하여 원하는 정보를 얻고 싶을 때 알맞은 유형의 Join 방법을 선택해서 사용할 수 있다.
기본적인 JOIN 의 유형의 종류는 다음과 같다.
위에서 LEFT 와 RIGHT 조인은 Left 또는 Right 테이블을 어떤 테이블로 잡는지만 다를뿐 똑같은 조합방법을 사용하기에 하나로 봐도 무방하다.
또한 LEFT,RIGHT JOIN은 OUTER JOIN 으로도 불릴 수 있으니 참고하자.
조건에 따라 교집합 부분을 제외한 outer join이 될 수 있기도 하고, 그게 아니기도 하다.
SELECT A.*, B.*
FROM raw_data.table1 as A
___JOIN raw_data.table2 as B
ON A.key1 = B.key1 and A.key2 = B.key2
WHERE A.ts >= '2024.01.01';
위와 같은 방식이 기본적인 SQL-JOIN 문법이다 ___JOIN 부분에 위에서 본 다양한 유형중 원하는 유형의 Join명을 명시하여 서로 다른 테이블을 특정한 컬럼값을 기준으로 조합할 수 있다.
각각의 테이블을 조합할 때 필요한 조건을 그 뒤 ON Condition에 명시하여 어떠한 조건으로 조합할 지 알려줌으로써 조건에 맞도록 각각의 테이블을 조합하여 하나의 테이블로 나타낸다.
___ 에 올 수 있는 키워드
CROSS JOIN 을 한다면 뒤에 오는 Condition은 의미가 없을 수 있다. 왜냐하면 CROSS JOIN은 각각의 컬럼별로 유의미한 조합을 모두 찾아내기 때문이다.
Join을 할 때 주의해야할 할 여러 가지 사항이 있다. 이 중 특히 중요한 두 가지 사항을 살펴보자.
| CUSTOMERID | NAME |
|---|---|
| 1 | Alice |
| 2 | Bob |
| OrderID | CustomerID | Product |
|---|---|---|
| 1001 | 1 | Laptop |
| 1002 | 1 | Mouse |
| 1003 | 2 | KeyBoard |
위 예시에서 CustomerID 는 고객 테이블에서 PK로 유일하다. 그러나 고객이 여러 주문을 할 수 있으므로 주문테이블에서 CustomerID 는 중복될 수 있다 이러한 경우 고객과 주문을 JOIN 하면 고객이 주문한 모든 항목이 표시된다.
SELECT Customers.Name, Orders.Product
FROM Customers
JOIN Orders
ON Customers.CustomerID = Orders.CustomerID;
위와 같은 쿼리를 작성하여 결과를 조회하면
| Name | Product |
|---|---|
| Alice | Laptop |
| Alice | Mouse |
| Bob | KeyBoard |
이와 같이 중복된 레코드를 생성할 수 있다. 따라서 PK 의 유일성을 보장하지 않는다면 원하지 않는 중복 레코드가 발생할 수 있으니 항상 사용하기 전에 이점을 유의해서 사용해야한다.
| UserID | UserName |
|---|---|
| 1 | Alice |
| 2 | Bob |
| ProfileID | UserID | Age |
|---|---|---|
| 1 | 1 | 30 |
| 2 | 2 | 25 |
이 경우 각 사용자들은 하나의 프로필만 연결되어 있기 때문에 이러한 관계에서 Join을 통해 사용자와 프로필 정보를 결합하여 사용자의 프로필 정보를 조회할 수 있다.
One to Many 또는 Many to One : 한 테이블의 한 레코드가 다른 테이블의 여러 레코드와 연결되는 경우.
이번에도 예시를 통해 어떠한 경우 이러한 경우에 해당하는지 알아보자.
작가 테이블
| AuthorID | Name |
|---|---|
| 1 | Alice |
| 2 | Bob |
| BookID | AuthorID | Title |
|---|---|---|
| 1 | 1 | Book A |
| 2 | 1 | Book B |
| 3 | 2 | Book C |
이러한 경우 한 작가는 여러가지 책을 출판했을 수 있기 때문에 작가가 어떤 책들을 출판했는지 알아보고자 하는 경우와 같을 때 Join 을 사용하면 원하는 결과를 얻을 수 있다.
Many to Many : 한 테이블의 여러 레코드가 다른 테이블의 여러 레코드들과 연결되는 경우.
이경우는 많이 발생되는 경우는 아니지만 이번에도 예를들어 한번 알아보자.
학생 테이블
| StudentID | Name |
|---|---|
| 1 | Alice |
| 2 | Bob |
| SubjectID | Title |
|---|---|
| 1 | Math |
| 2 | Science |
| StudentID | SubjectID |
|---|---|
| 1 | 1 |
| 1 | 2 |
| 2 | 1 |
이러한 경우 한 학생이 여러 과목을 수강할 수 있고, 한 과목에 여러 학생이 수강할 수 있다. 이처럼 다대다의 관계가 있을 때 이또한 Join 을 통해 알 수 있다.
결국 JOIN을 사용하기에 앞서 PK의 유일성과 각 테이블간의 관계를 명확하게 알고 사용하다면 예상치 못한 결과를 방지하고, 쿼리를 더욱더 효과적으로 작성할 수 있다.