본문 바로가기

CS+/SQL

SQL JOIN - left join, inner join (feat. MY SQL)

SQL을 공부한다면, 꼭 알아야하는 개념이 'JOIN'입니다. 

이번 시간에는 이에 대해 차근차근 설명해보도록 하겠습니다. 

 

먼저, 곱집합에 대해서 설명하겠습니다.

 

 

출처:https://bit.ly/37g2xwD

3개의 원소를 가진 2개의 집합을 곱하면 총 9쌍의 원소로 이루어진 집합이 생깁니다. 

mysql 로 확인해보겠습니다.

 

 

2개의 테이블(=집합)이 있습니다. 각각 원소가 3개씩 들었는데, 

이를 카티전 곱 해보겠습니다. 간단합니다.

 

 

 

두 개의 테이블을 콤마(,)로 연결했더니, 곱집합이 생겼습니다. 3 x 3 으로 9 개의 원소가 되었습니다. 

 

Point! 

From 구에 복수의 테이블을 지정하면 교차결합(=곱집합)을 한다!

데이터를 넣어본 테이블로 다시 보겠습니다.

 

 

 

3개의 로우(데이터)가 들은 2개의 테이블이 있습니다. 이를 내부결합할건데요. 

그전에 각 테이블에 '상품코드'라는 칼럼이 보이나요? 기본키라는 개념입니다. 

 

기본 키(primary key)는 주 키 또는 프라이머리 키라고 하며, 관계형 데이터베이스에서 조(레코드)의 식별자로 이용하기에 가장 적합한 것을 관계 (테이블)마다 단 한 설계자에 의해 선택, 정의된 후보 키를 말한다. 유일 키는 0~1개 이상의 속성의 집합으로 볼 수 있다.[1] 즉, 관계에 저장된 레코드를 고유하게 식별하는 후보 키 (=속성 또는 속성의 집합) 가운데, 설계자가 일반적으로 이용되어야한다고 정해 놓은 것을 가리킨다.

 

라고 위키백과에서 설명합니다. 굳이, 더 자세히 말 안하겠습니다. 따로, 찾아보시길...

 

 

 

콤마를 통해서 기본키가 있는 테이블들을 내부결합하였습니다. 

= from 구에 테이블을 복수로 지정하면 곱집합으로 표현됩니다. 

 

하지만, 우리는 모든 데이터를 다 결합해서 보려는 게 목적이 아닙니다. 필요한 데이터만! 보고 싶습니다.

이를 위해 where 구로 조건을 지정합니다. 이 때, 기본키가 들어간 테이블이어야 합니다. 만약, 두 개의 테이블에 키가 없다면 검색이 되지 않습니다. 

1) inner join 

- null 값이 있는 로우는 제거한다.

 

자, 이제 2개의 테이블의 상품코드 같은 제품만 보겠습니다. 

상품 테이블의 상품코드 = 제품 테이블의 제품코드가 같은 애들만 보겠습니다. 위 사진을 보면, 우리는 모든 경우의 쌍(=곱집합)을 다 볼 필요가 없습니다. 코드가 맞는 애들이 실제 그 상품이 갖고 있는 속성들이 있으므로 그것만 선택해서 보아야 합니다. 

 

 

 

위처럼 표현해주면 됩니다. 하나하나 보겠습니다.

 

from 상품1, 상품2 : 2개의 테이블을 곱집합해서 모든 데이터의 결합된 경우의 수라는 테이블 가상으로 생성 

where 상품.상품코드 = 재고수.상품코드 : 옆의 조건이 true인 로우만 보여줘! 

 

from 절에서 테이블이 가상으로 생성된다고 표현했는데 맞는 표현인지는 모르겠습니다. 실제, 작동이 그렇게 되는지도 모르겠구요. 다만 이해하기 쉽게 먼저 큰 틀을 짜고(=곱집합으로 만들고) 거기서 필요한 거만 where 구로 꺼내온다. 라고 생각하면 이해가 쉽지 않을까 싶습니다.

 

위와 같은 경우를 Inner Join한다고 합니다. 

여기서 좀 더 필터를 줘보겠습니다. 

 

 

 

조건을 하나 더 추가하면 필터가 되겠지요? 

이제,일반화 해보겠습니다.

 

 

출처:https://sql-joins.leopard.in.ua/

 

> SELECT * FROM TableA , TableB where TableA.column1= TableB. column1 

> SELECT * FROM TableA A INNER JOIN TableB B ON A.key = B.key

 

inner join 의 2가지 표현형태입니다. 둘 다 알고 계셔야 합니다. 

직접적으로 00 join 이라는 표현을 쓸 때는  A 00 JOIN B ON 조건식 으로 표현합니다. 

본인이 표현한 걸로 표기하면 되지만, 둘 다 알아야 다른 사람의 쿼리문을 읽을 수 있으니 둘 다 숙지하시길 바랍니다.

 

근데, Inner Join 은 잘 쓰지 않습니다. 그리고 모든 칼럼을 선택하지도 않습니다. 

생각을 좀 해보자면, 우리가 이러한 필터를 하는 이유는 필요한 것만!!!! 보기 위해서입니다. 칼럼이 많아진다면,

우리가 봐야할 칼럼이 눈에 잘 들어오지 않습니다. 

 

 

예를 보겠습니다.

 

 

 

겹치는 칼럼을 제외하더라도 칼럼이 합치면 6개입니다. 실제로는 모두 보아도 적을 수 있겠지만, 실무에서는 칼럼이 어마어마하게 많고, 로우는 더 말할 것도 없습니다. 만약, 칼럼이 합쳤을 때 30개가 넘는다면 그걸 다 일일히 볼 필요가 있을까요? 아니 다 출력되도 눈에 잘 들어올까요? 그렇지 않을 겁니다. 

 

아래도 inner join의 예시 쿼리입니다. 

테이블에 각각에 대해서는 left join 설명 초반에 보여드렸습니다. (아래에 스크롤 내리다 보면 있습니다.)

 

 

 

inner join 에서는 Null 값이 있는 로우는 없는게 보입니다. 왜일까요? 

개념 자체가 교집합이니깐요. 

양쪽 테이블에 다 값이 있어야 하므로 inner join에서는  null을 취급하지 않습니다.

 

자 이제, Join 한 다음에는 필요한 열만 선택해주세요.

아래의 쿼리문은 left join을 한 건데요. 

칼럼 선택하는 법만을 봐주시고, 

바로 밑에서 left join 설명을 읽어보시고 다시 스크롤 올려서 봐주시면 이해가 잘 될 것 같습니다~

 

 

 

이제 감이 좀... 

 

 

.

 

 

.

 

 

 

.

 

 

잘 안올거라 생각합니다 ㅎㅎ

좀 더 예시를 봐야합니다. 

 

2) left join 

- null 값이 보인다. 

- 좌측 테이블 기준으로 우측 테이블을 합치지만, 우측 테이블에 같은 값이 없으면,

null 값으로 채워진다. 

 

 

이제, left join 을 살펴보겠습니다. 

 

left join은 위와 같습니다. 2개의 테이블을 나열할 때, 왼쪽을 기준으로 거기에 있는 칼럼만 보는 겁니다.

 

> SELECT * FROM TableA A LEFT JOIN TableB B ON A.key = B.key WHERE B.key IS NULL

 

예시를 보겠습니다. 

아래의 두 테이블이 있습니다. (생활코딩 참고!)

 

 

이를 topic 테이블 기준으로 left join 하겠습니다.

 

 

from topic left join author : topic 테이블을 왼쪽에 두고, 오른쪽에 author 테이블 놓을게~

on topic.author_id = author.aid /// 해석: topic테이블의 author_id 칼럼과 author 테이블의 aid 칼럼 값이 같은 애들만!!!참고해서

하나의 테이블로 만들어줘!!

 

이제 조금 이해가 되나요?

근데 왼쪽 테이블 기준으로 합쳐주는 건 알겠는데...왜 Null 이 들어가있을까? 

 

author_id 에 null값이 있는 로우가 하나 보이죠? 여기에 오른쪽 테이블 aid와 값이 같은애 있어야 되는데 없죠? 

없는 애들은 그냥 null 로 채웁니다. 있는 애들은 잘 붙여지는데 없는 id 값은 그냥 Null로 채워지는구나! 하고 이해하시면 되요. 

 

기준 칼럼들을 봤을 때, 왼쪽 칼럼에 있지만, 오른쪽 테이블에 없구나! 라는거죠. 만약 null이 아니라 3이라면? 그래도 author aid에는 3에 대한 값이 없죠? 그러니 똑같이 null로 채워질 겁니다. 

 

아하! 그러면 left join 했는데 오른쪽 칼럼 애들 값이 들어왔는데 다 null이라면? 걔는 우측 테이블 값에 맞는애가 없는애구나! 하고 이해하실 수 있습니다! 찬찬히 코드를 보시면서 음미해보시길!

 

자, 위에 left join 은 2개의 테이블을 했죠. 여기다가 그대로 하나 더 left join 해보겠습니다. 

 

 

기존 코드에 하나가 더 추가됐을 뿐입니다. 

근데, 칼럼을 전부 다 선택하니깐 지저분하죠? 그리고 autho_id, aid, profile_id, pid 는 키값인데 합치는 중에는 중요하지만, 굳이 출력해서 모두 볼 필요는 없습니다.

 

그러니, 필요한 칼럼만 선택을 해줘야합니다!

 

 

 

가만보면, 어떤 칼럼은 그냥 칼럼 이름만, 어떤 칼럼은 테이블이름과 같이 써줬습니다. 

왜 그럴까요? 

모든 테이블을 통틀어서 유일한 칼럼 이름이라면 굳이 테이블 이름 안써도 db가 알아서 그 칼럼을 인식합니다.

근데, 칼럼 이름이 같은 게 여러 테이블에 있다면 표시를 해줘야합니다. 

 

그리고 from 절에서 테이블 이름에 별명을 지어줘서 그걸로 

테이블별명.칼럼이름

이렇게 해줘도 됩니다. 아니 이게 더 편합니다. 

원래 별명 만들 때는 as 하고싶은 별명 을 해줘도 되지만 스페이스바(한칸 건너뛰고) 별명만 써도 됩니다. 

사실 이게 더 편합니다! 

 

여기서 내가 보고 싶은 코드가 일치하는 사람만 위와 같이 볼 수 있습니다. 

 

 

다음 시간에는 Outer join 을 다루겠습니다.

그리고 oracle 로도 join을 하는 것을 한 번 다뤄보도록 하겠습니다.

 

 

 

**참고** 

https://opentutorials.org/course/3884

 

SQL Join - 생활코딩

수업소개 관계형 데이터베이스에서 테이블과 테이블의 관계를 이용해서 새로운 테이블을 만들어내는 태크닉인 join을 알려드리는 수업입니다.  이 수업은 아래와 같은 내용을 다루고 있습니다.  테이블을 분리하는 법 분리 된 테이블을 합성해서 하나의 테이블로 만드는 법 (join) join의 종류와 사용법 inner join left outer join, right outer join full outer join 아래 내용은 다루고 있지 않습니다.  데이터베이스

opentutorials.org

https://bit.ly/2OKvA4V