SQL JOIN 정리 | INNER JOIN, LEFT JOIN, RIGHT JOIN 차이 이해하기

JOIN은 여러 테이블에 나뉘어 있는 데이터를 하나의 결과처럼 연결해서 조회하는 SQL 문법이다. RDBMS에서는 데이터를 하나의 큰 테이블에 모두 넣지 않고 여러 테이블로 나누어 관리하기 때문에, 실제 조회에서는 JOIN을 자주 사용한다.


JOIN이 필요한 이유

예를 들어 회원 정보와 영화 정보가 서로 다른 테이블에 저장되어 있다고 하자.

members 테이블 → 회원 정보
movies 테이블  → 영화 정보

회원 테이블에는 회원이 선택한 영화 ID만 있고, 영화 제목은 영화 테이블에 있다면 한 테이블만 조회해서는 원하는 결과를 만들기 어렵다.

이때 두 테이블을 연결하는 기준이 필요하다.

members.movie_id = movies.id

이 조건을 기준으로 회원 정보와 영화 정보를 연결하는 것이 JOIN이다.


예시 테이블 구조

create database if not exists test_join
default character set utf8mb4
collate utf8mb4_0900_ai_ci;

use test_join;

create table members (
    id int not null,
    first_name varchar(45),
    last_name varchar(45),
    movie_id int,
    primary key (id)
);

create table movies (
    id int not null,
    title varchar(45),
    category varchar(45),
    primary key (id)
);

여기서 연결 기준은 members.movie_id와 movies.id다.

members.movie_id → 회원이 선택한 영화 ID
movies.id        → 영화 테이블의 영화 ID

CROSS JOIN

CROSS JOIN은 두 테이블의 모든 조합을 만든다.

select *
from movies cross join members;

예를 들어 영화가 3개, 회원이 5명이라면 결과는 15개가 된다.

연결 조건 없이 가능한 모든 조합을 만들기 때문에, 일반적인 데이터 조회에서는 자주 쓰이지 않는다.


INNER JOIN

INNER JOIN은 양쪽 테이블에서 연결 조건이 일치하는 데이터만 조회한다.

select *
from members ME inner join movies M
    on ME.movie_id = M.id;

여기서 on은 두 테이블을 어떤 기준으로 연결할지 정하는 조건이다.

ME.movie_id = M.id

이 조건이 맞는 회원과 영화만 결과에 나온다.


필요한 컬럼만 조회하기

JOIN 결과에서 모든 컬럼이 필요한 경우는 많지 않다.

보통은 필요한 컬럼만 골라서 조회한다.

select
    M.title,
    ME.first_name,
    ME.last_name
from members ME inner join movies M
    on ME.movie_id = M.id;

이 쿼리는 회원 이름과 해당 회원이 연결된 영화 제목만 보여준다.


테이블 별칭을 쓰는 이유

JOIN에서는 테이블명이 길어지기 쉽다.

그래서 보통 별칭을 붙여 쓴다.

members ME
movies M

이후에는 컬럼 앞에 별칭을 붙여 구분한다.

ME.first_name
M.title

이 방식은 가독성뿐 아니라 컬럼명 충돌을 막는 데도 필요하다.


컬럼명이 겹칠 때 주의할 점

두 테이블에 같은 이름의 컬럼이 있으면 SQL은 어느 테이블의 컬럼인지 판단하기 어렵다.

예를 들어 members에도 id가 있고, movies에도 id가 있다.

select id, title, first_name, last_name
from members ME inner join movies M
    on ME.movie_id = M.id;

이 쿼리는 id가 어느 테이블의 id인지 모호할 수 있다.

따라서 아래처럼 테이블 별칭을 붙이는 것이 안전하다.

select
    M.id,
    M.title,
    ME.first_name,
    ME.last_name
from members ME inner join movies M
    on ME.movie_id = M.id;

JOIN에서는 컬럼명이 겹칠 가능성이 높기 때문에, 중요한 컬럼에는 별칭을 붙여 명확히 쓰는 습관이 좋다.


LEFT JOIN

LEFT JOIN은 왼쪽 테이블을 기준으로 전체 데이터를 가져오고, 오른쪽 테이블에서 연결되는 값이 있으면 붙인다.

select
    M.id,
    M.title,
    ME.first_name,
    ME.last_name
from movies M left join members ME
    on M.id = ME.movie_id;

이 쿼리는 movies 테이블을 기준으로 한다.

즉, 회원이 선택하지 않은 영화라도 movies에 있으면 결과에 나온다.

연결되는 회원이 없으면 회원 컬럼은 NULL로 표시된다.

왼쪽 테이블 전체 유지
오른쪽 테이블은 매칭되는 값만 연결

RIGHT JOIN

RIGHT JOIN은 오른쪽 테이블을 기준으로 전체 데이터를 가져오고, 왼쪽 테이블에서 연결되는 값이 있으면 붙인다.

select
    M.id,
    M.title,
    ME.first_name,
    ME.last_name
from members ME right join movies M
    on M.id = ME.movie_id;

이 쿼리는 오른쪽에 있는 movies 테이블을 기준으로 한다.

위의 LEFT JOIN 예시와 테이블 순서만 다를 뿐, 같은 목적의 결과를 만들 수 있다.

실무에서는 보통 RIGHT JOIN보다 LEFT JOIN을 더 자주 쓴다.

기준이 되는 테이블을 왼쪽에 두면 쿼리 흐름을 읽기 쉽기 때문이다.


INNER JOIN, LEFT JOIN, RIGHT JOIN 차이

JOIN 종류 결과 기준

INNER JOIN 양쪽 테이블에 모두 매칭되는 데이터
LEFT JOIN 왼쪽 테이블 전체 + 오른쪽 매칭 데이터
RIGHT JOIN 오른쪽 테이블 전체 + 왼쪽 매칭 데이터
CROSS JOIN 두 테이블의 모든 조합

JOIN에서 가장 중요한 것은 ON 조건

JOIN 문법에서 가장 중요한 부분은 on이다.

on ME.movie_id = M.id

ON 조건이 잘못되면 전혀 다른 결과가 나온다.

JOIN을 작성할 때는 먼저 “두 테이블이 어떤 컬럼으로 연결되는지”를 확인해야 한다.

회원 테이블의 movie_id
영화 테이블의 id

이처럼 연결 기준을 명확히 잡는 것이 JOIN의 시작이다.


JOIN은 여러 테이블을 공통 컬럼 기준으로 연결해 하나의 결과처럼 조회하는 SQL 문법이다.