SQL INNER JOIN 에 대한 이해

이한재·2023년 1월 17일
0
post-thumbnail

SQL 에서 INNER JOIN 은 교집합과 같다.

예를 들어 인스타그램과 같은 웹서비스를 만든다고 가정했을때

데이터베이스의 구조가

users 테이블이 다음과 같고

posts 테이블이 다음과 같을 경우

users 가 작성한 게시물들에 대한 정보를 posts 의 데이터와 함께 보여주고 싶을 경우가 있을 수 있다.

따라서

users 와 posts 의 있는 데이터중 공통된 값만 결과값으로 가져오고 싶을 경우
INNER JOIN 을 활용 하면 된다.

이것을 SQL 문으로 표현하면 다음과 같다

SELECT * FROM users INNER JOIN posts ON users.id = posts.user_id;

posts 테이블에 users 테이블의 id를 참조하는 user_id 라는 Foreign Key 가 있기 때문에
ON 조건에서 users 의 id 와 posts 의 user_id 의 값이 일치하는 경우에 대한 값을 가져오게되면

users 테이블과 posts 테이블을 합친 데이터들 중에서 users.id 와 posts.user_id 가 같은 데이터에 대해서만 가져오겠다는 의미이다.

SQL 에서 JOIN 이란 것은 결국 테이블을 결합하겠다는 의미이고 그 중 INNER JOIN 은 결합된 테이블간의 공통된 값만 가져온 결과값을 반환한다.

앞에서는 테이블을 users 와 posts 라는 2개의 테이블만 결합했다. 하지만 3개이상의 테이블을 결합해야 하는 상황을 가정해보자

likes 라는 테이블은 다음과 같고 총 user_id 와 post_id 에 대해 Foreign key 제약조건이 걸려있다.

user_id 는 users.id 를 참조할 것이고 post_id 는 posts.id 를 참조할 것이다.

그럼 이렇게 users, posts, likes 총 3개의 테이블을 결합해서

  1. 어떤 한 유저가 작성한 게시물에 대한 정보
  2. 작성한 유저에 대한 정보
  3. 좋아요를 한 유저에 대한 정보

로 총 세가지 다른 테이블로부터 가져온 정보를 합쳐서 보여줘야 하는 상황이 생길 수 있다.

이것을 SQL 문으로 구현해보면

SELECT * FROM users
-> INNER JOIN posts
-> ON users.id = posts.user_id
-> INNER JOIN likes
-> ON users.id = likes.user_id;

위의 코드 처럼 작성 할 수 있다.

하지만 이렇게 했을 경우 likes 테이블을 결합을 해서 likes 테이블의 user_id 는 가져와서 user_id 에 대한 정보는 가지고 있지만 어떤 이름을 가진 유저가 게시물에 대하여 좋아요를 눌렀는지는 알 수 없다.

그럼 이렇게 가져온 likes.user_id 를 가지고 users 테이블을 INNER JOIN 해보면 좋아요를 누른 사용자의 이름을 가져 올 수 있을 것이다.

좋아요를 누른 사용자의 이름까지 함께 가져오려면 다음과 같다.

SELECT * FROM users 
INNER JOIN posts 
ON users.id = posts.user_id 
INNER JOIN likes ON posts.id = likes.post_id 
INNER JOIN users;

위의 문장 처럼 총 INNER JOIN 이 3번 들어가는 과정이 들어갈 것이다.
하지만 이렇게 했을때 mysql 에서 실행해보면
ERROR 1066 (42000): Not unique table/alias: 'users'
라는 에러가 출력된다

에러를 해석해보면 'users' 라는 테이블을 mysql 이 인식하지 못하는 것 같다.
왜냐하면 최초에 SELECT FROM 구문에서 users 로 한번 가져오고 마지막 INNER JOIN 에서도 users 테이블을 결합하는 과정에 있기 때문이다
따라서 이 문제점을 해결하려면 AS 로 table 의 별칭을 지정해주면 해결된다.

SELECT authors.name AS author, posts.title, posts.content, like_users.name AS like_user 
FROM users AS authors 
INNER JOIN posts ON authors.id = posts.user_id 
INNER JOIN likes ON posts.id = likes.post_id 
INNER JOIN users AS like_users ON like_users.id = likes.user_id;

sql 이 SELECT FROM 으로 가져온 users 테이블과 마지막 INNER JOIN 구문에서 가져온 users 가 같다고 인식하여 생기는 문제점이었고
이를 해결하기 위해 앞부분의 users 테이블을 authors 라고 칭하고
뒷부분의 users 테이블을 like_users 라고 칭했다.

또한 구분지어 놓은 테이블의 컬럼에 대해서도 어떤 역할을 하는 데이터인지 구분 짓기 위해 authors.name AS author, like_users.name AS like_user 로
작성자와 좋아요를 누른 유저의 이름을 명확하게 구분 지어 볼 수 있도록 하였다.

따라서 위 사진 처럼 목표했던

  1. 어떤 한 유저가 작성한 게시물에 대한 정보
  2. 작성한 유저에 대한 정보
  3. 좋아요를 한 유저에 대한 정보

이 세가지를 가져올 수 있었고

여기서 중요한 포인트 두가지 정도로 볼 수 있는데

  1. 테이블을 3개를 결합하기 위해 INNER JOIN 이 2개만 필요한 것이 아니라
    내가 필요한 정보의 성격에 따라서 3개를 결합하더라도 INNER JOIN 이 3개 혹은 그 이상이 될 수도 있다고 느꼈다.

  2. 위처럼 JOIN을 통해 어떤 한 테이블을 두번 이상 가져올 경우
    FROM 절에서 가져온 테이블인지
    JOIN 절에서 가져온 테이블인지
    mysql 내에서 어떤 테이블을 지칭하는지 인식 할 수 없기 때문에
    AS (alias) 키워드로 별칭을 지정해주게 되면
    결국 같은 테이블이라고 하더라도 별칭을 통해 SQL 문장을 작성 할 수 있기 때문에
    한 테이블을 두번 이상 가져오더라도 충돌없이 가져온 테이블에 대하여 접근 할 수 있다.

추가적으로 이렇게 이미 가져온 테이블에 대하여 JOIN 을 하게되는 경우 SELF JOIN 이라고 부르는데
SELF JOIN 에 대한 이해를 하는 것도 SQL 을 이해하는데 도움이 될 수 있을 것이다.

*참고자료 : https://sql-joins.leopard.in.ua/

profile
이한재입니다

0개의 댓글