SQL - JOIN 다루기 기초

jomminii_before·2020년 2월 12일
0

Database-series

목록 보기
2/6

"Every table in the database needs to have a single theme. - 모든 테이블은 하나의 주제만 가져야 한다."

관계형 데이터베이스를 만든 분이 위와 같은 말을 했다고 하는데, 관계형 데이터 테이블이 가져야할 최소한의 규칙이 아닌가 싶네요.

관계형 데이터 테이블의 경우 주제별로 테이블을 나누어 놓으면, 추후 수정사항이 생겼을 때 해당 테이블에서만 데이터를 수정하면 다른 모든 데이터에 반영되어 편리합니다.

반면 기존의 테이블의 경우에는 데이터가 한 테이블에 있어 읽기는 좋지만, 위와 같은 수정사항이 생겼을 때는 작업을 하기 어렵다는 단점이 있습니다.

이러한 trade-off 적인 요소를 보완하기 위해 나온 기능이 데이터베이스의 JOIN 기능입니다. 관리는 관계형 데이터 모델로 하고, 필요할 경우 필요한 요소들을 모아 보기 쉬운 테이블을 생성해주는 기능이죠.

JOIN 사용하기

생활코딩에서 예시로 보여준 테이블을 활용해 JOIN 사용법을 알아보겠습니다. MySQL을 사용해 테이블을 조작할 예정이므로, 아직 MySQL에 익숙하지 않으신 분은 아래 글을 참조해보세요!


LEFT JOIN

LEFT JOIN은 기준으로 둔 테이블을 왼쪽에 두고, 이 테이블의 데이터를 기준으로 다음 테이블의 데이터를 정렬하는 방식 입니다.

왼쪽 테이블의 값은 모두 노출되야하기 때문에, 만약에 오른쪽 테이블에 왼쪽 테이블과 맞는 값이 없다면 NULL로 데이터가 채워집니다.

먼저 topicauthor 테이블을 LEFT JOIN 해보겠습니다.


# 명령어 구성
$ SELECT * FROM TableA LEFT JOIN TableB ON A.key = B.key 

# 실제 명령어 작성
$ mysql> select * from topic left join author on topic.author_id = author.aid;
+-----+------------+------------------+-----------+------+---------+-------+------------+
| tid | title      | description      | author_id | aid  | name    | city  | profile_id |
+-----+------------+------------------+-----------+------+---------+-------+------------+
|   1 | HTML       | HTML is ...      | 1         |    1 | egoing  | seoul |          1 |
|   2 | CSS        | CSS is ...       | 2         |    2 | leezche | jeju  |          2 |
|   3 | JavaScript | JavaScript is .. | 1         |    1 | egoing  | seoul |          1 |
|   4 | Database   | Database is ...  | NULL      | NULL | NULL    | NULL  |       NULL |
+-----+------------+------------------+-----------+------+---------+-------+------------+
4 rows in set (0.00 sec)

출력된 결과물을 보면, topic을 구성하는 모든 행을 기준으로 데이터가 출력되었고, author의 데이터 중 [topicauthor_id]와 연결되는 값이 없는 [aid=3] 값은 출력되지 않았습니다. 그리고 [topictid=4]와 연결되는 author의 데이터가 존재하지 않아, 해당 행의 author 데이터는 모두 NULL로 처리되었습니다.


이번에는 LEFT JOIN으로 테이블 하나를 더 합쳐보겠습니다.

$ mysql> select * from topic left join author on topic.author_id = author.aid left join profile on author.profile_id = profile.pid;
+-----+------------+------------------+-----------+------+---------+-------+------------+------+-----------+------------------+
| tid | title      | description      | author_id | aid  | name    | city  | profile_id | pid  | title     | description      |
+-----+------------+------------------+-----------+------+---------+-------+------------+------+-----------+------------------+
|   1 | HTML       | HTML is ...      | 1         |    1 | egoing  | seoul |          1 |    1 | developer | developer is ... |
|   2 | CSS        | CSS is ...       | 2         |    2 | leezche | jeju  |          2 |    2 | designer  | designer is ..   |
|   3 | JavaScript | JavaScript is .. | 1         |    1 | egoing  | seoul |          1 |    1 | developer | developer is ... |
|   4 | Database   | Database is ...  | NULL      | NULL | NULL    | NULL  |       NULL | NULL | NULL      | NULL             |
+-----+------------+------------------+-----------+------+---------+-------+------------+------+-----------+------------------+
4 rows in set (0.00 sec)

동일한 규칙으로 두번째 테이블의 값과 세번째 테이블의 값을 매칭시켜서 값을 가져왔습니다. 근데 각각의 테이블의 인덱스와 같은 이름의 필드값들이 한데 모이니 좀 지저분해 보입니다. 여기서 우리는 원하는 필드를 출력하고, 또 필드명을 다른 이름으로 바꿈으로써 테이블을 보기 좋게 수정할 수 있습니다.


먼저 원하는 값을 뽑아봅시다. 저는 [tid, title, name, city, title] 정보를 뽑아보고 싶습니다. 이러기 위해서는 select 다음에 오는 [*] 값을 바꿔주면 됩니다.

이제 명령어를 바꿔쳐보면, $ mysql> select tid, title, name, city, title...? 치다보니 앞에서 쳤던 [title]이 또 나옵니다. 이렇게 같은 값이 여러번 나오면 SQL은 어떤 값을 달라는건지 알지 못해서 에러가 뜹니다.

ERROR 1052 (23000): Column 'title' in field list is ambiguous

이때는 겹치는 값을 특정 테이블의 값이라고 특정해주면 됩니다.

topic에 있는 title[topic.title]로 바꾸고, profiletitlejob_title으로 바꿔서 출력하기 위해 [profile.title as job_title]로 바꿔줍니다.

그러면 짠 하고 원하는 테이블이 나타납니다.

$ mysql> select tid, topic.title, name, city, profile.title as job_title from topic left join author on topic.author_id = author.aid left join profile on author.profile_id = profile.pid;
+-----+------------+---------+-------+-----------+
| tid | title      | name    | city  | job_title |
+-----+------------+---------+-------+-----------+
|   1 | HTML       | egoing  | seoul | developer |
|   2 | CSS        | leezche | jeju  | designer  |
|   3 | JavaScript | egoing  | seoul | developer |
|   4 | Database   | NULL    | NULL  | NULL      |
+-----+------------+---------+-------+-----------+
4 rows in set (0.00 sec)

INNER JOIN

INNER JOIN은 불러오는 테이블의 교집합이라고 보면 됩니다. 각 테이블에 동시에 존재하는 값들만 새로운 테이블로 출력됩니다. 그렇기 때문에 INNER JOIN에는 테이블간 비매칭으로 인한 NULL 값은 존재하지 않습니다. 꽤나 기준이 엄격한 모델이라고 할 수 있죠.

먼저 topicauthor 테이블을 INNER JOIN 해보겠습니다. LEFT JOIN 때와 다르게 topictid=4값이 사라졌습니다. topic에만 데이터가 있어서 출력되지 않은거죠.


# 명령어 구성
$ SELECT * FROM TableA INNER JOIN TableB ON A.key = B.key 

# 실제 명령어 작성
$ mysql> select * from topic inner join author on topic.author_id = author.aid;
+-----+------------+------------------+-----------+-----+---------+-------+------------+
| tid | title      | description      | author_id | aid | name    | city  | profile_id |
+-----+------------+------------------+-----------+-----+---------+-------+------------+
|   1 | HTML       | HTML is ...      | 1         |   1 | egoing  | seoul |          1 |
|   2 | CSS        | CSS is ...       | 2         |   2 | leezche | jeju  |          2 |
|   3 | JavaScript | JavaScript is .. | 1         |   1 | egoing  | seoul |          1 |
+-----+------------+------------------+-----------+-----+---------+-------+------------+
3 rows in set (0.00 sec)

이번에는 테이블 하나를 더 추가해서 출력해보겠습니다.

# mysql> select tid, topic.title, name,city,profile.title as job_title from topic inner join author on topic.author_id = author.aid inner join profile on author.profile_id = profile.pid;
+-----+------------+---------+-------+-----------+
| tid | title      | name    | city  | job_title |
+-----+------------+---------+-------+-----------+
|   1 | HTML       | egoing  | seoul | developer |
|   2 | CSS        | leezche | jeju  | designer  |
|   3 | JavaScript | egoing  | seoul | developer |
+-----+------------+---------+-------+-----------+
3 rows in set (0.00 sec)

여기서도 LEFT JOIN 때와 다르게 NULL 값이 포함된 열은 출력되지 않은 것을 알 수 있습니다.

이외 JOIN

이외 JOIN에는 RIGHT, FULL OUTER, EXCLUSIVE가 있는데, 사용빈도가 높지 않아 간단히 설명하고 끝마치려 합니다.

  • RIGHT JOIN : LEFT JOIN과 반대로 오른쪽을 기준으로 출력
  • FULL OUTER JOIN : 합집합이라고 보면되며, 이 방식을 제공하지 않는 데이터베이스에서는 UNION을 사용해 합칠 수 있음. 합친 후 중복을 제거해 줌
  • EXCLUSIVE JOIN : 특정 테이블에 있는 값만 출력해줌

참고자료

profile
https://velog.io/@jomminii 로 이동했습니다.

0개의 댓글