SQL - JOIN의 종류와 활용 + UNION

StrayCat·2026년 2월 22일

CS지식

목록 보기
4/32

예시 테이블 구조

-- 사용자 테이블
CREATE TABLE users (
    id   INT PRIMARY KEY,
    name VARCHAR(50)
);

-- 주문 테이블
CREATE TABLE orders (
    id      INT PRIMARY KEY,
    user_id INT,  -- users.id 참조 (FK)
    product VARCHAR(50)
);
users 테이블         orders 테이블
┌────┬────────┐     ┌────┬─────────┬──────────┐
│ id │ name   │     │ id │ user_id │ product  │
├────┼────────┤     ├────┼─────────┼──────────┤
│  1 │ Alice  │     │  1 │    1    │ iPhone   │
│  2 │ Bob    │     │  2 │    1    │ iPad     │
│  3 │ Charlie│     │  3 │    2    │ MacBook  │
│  4 │ Dave   │     │  4 │    99   │ AirPods  │ ← user_id 99는 없는 유저
└────┴────────┘     └────┴─────────┴──────────┘

1. INNER JOIN

두 테이블 모두에 매칭되는 데이터만 반환합니다.

SELECT u.name, o.product
FROM users u
INNER JOIN orders o ON u.id = o.user_id;
-- ON 절: 어떤 컬럼을 기준으로 연결할지 조건 지정
결과
┌───────┬─────────┐
│ name  │ product │
├───────┼─────────┤
│ Alice │ iPhone  │
│ Alice │ iPad    │
│ Bob   │ MacBook │
└───────┴─────────┘
-- Charlie, Dave: 주문 없음 → 제외
-- user_id=99 주문: 유저 없음 → 제외

활용 예시: 실제로 주문한 사용자와 주문 내역을 함께 조회할 때


2. LEFT (OUTER) JOIN

왼쪽 테이블은 모두 반환하고, 오른쪽에 매칭이 없으면 NULL로 채웁니다.

SELECT u.name, o.product
FROM users u
LEFT JOIN orders o ON u.id = o.user_id;
-- users(왼쪽)를 기준으로 모두 포함
결과
┌─────────┬─────────┐
│ name    │ product │
├─────────┼─────────┤
│ Alice   │ iPhone  │
│ Alice   │ iPad    │
│ Bob     │ MacBook │
│ Charlie │ NULL    │ ← 주문이 없어도 포함
│ Dave    │ NULL    │ ← 주문이 없어도 포함
└─────────┴─────────┘

활용 예시: 주문 여부와 관계없이 모든 사용자 목록을 조회할 때, 또는 주문 안 한 유저만 필터링할 때

-- 한 번도 주문하지 않은 사용자 조회
SELECT u.name
FROM users u
LEFT JOIN orders o ON u.id = o.user_id
WHERE o.id IS NULL;  -- NULL인 경우 = 매칭되는 주문이 없는 경우

3.RIGHT (OUTER) JOIN

오른쪽 테이블은 모두 반환하고, 왼쪽에 매칭이 없으면 NULL로 채웁니다.

SELECT u.name, o.product
FROM users u
RIGHT JOIN orders o ON u.id = o.user_id;
-- orders(오른쪽)를 기준으로 모두 포함
결과
┌───────┬─────────┐
│ name  │ product │
├───────┼─────────┤
│ Alice │ iPhone  │
│ Alice │ iPad    │
│ Bob   │ MacBook │
│ NULL  │ AirPods │ ← user_id=99 유저가 없어도 주문은 포함
└───────┴─────────┘

활용 예시: 유저 정보가 삭제됐더라도 주문 데이터를 전부 확인할 때

💡 대부분의 상황에서는 LEFT JOIN을 훨씬 더 많이 씁니다. RIGHT JOIN은 테이블 순서를 바꿔서 LEFT JOIN으로 대체 가능함을 기억.


4.FULL (OUTER) JOIN

양쪽 테이블 모두를 반환하고, 매칭 없는 쪽은 NULL로 채웁니다.

SELECT u.name, o.product
FROM users u
FULL OUTER JOIN orders o ON u.id = o.user_id;
결과
┌─────────┬─────────┐
│ name    │ product │
├─────────┼─────────┤
│ Alice   │ iPhone  │
│ Alice   │ iPad    │
│ Bob     │ MacBook │
│ Charlie │ NULL    │
│ Dave    │ NULL    │
│ NULL    │ AirPods │
└─────────┴─────────┘

⚠️ MySQL등 일부 RDBMS는 FULL OUTER JOIN을 지원하지 않습니다. LEFT JOIN + RIGHT JOINUNION으로 합쳐야 합니다.

-- MySQL에서 FULL OUTER JOIN 대체
SELECT u.name, o.product FROM users u LEFT  JOIN orders o ON u.id = o.user_id
UNION
SELECT u.name, o.product FROM users u RIGHT JOIN orders o ON u.id = o.user_id;

5. CROSS JOIN

모든 조합(카테시안 곱)을 반환합니다. 조건 없이 양쪽을 곱합니다.

SELECT u.name, o.product
FROM users u
CROSS JOIN orders o;
-- users 4행 × orders 4행 = 16행 반환

활용 예시: 모든 상품 × 모든 사용자 조합이 필요한 경우 (ex. 추천 시스템 초기 데이터 생성)


6. SELF JOIN

같은 테이블을 자기 자신과 조인합니다. 별칭(alias)을 다르게 줘서 사용합니다.

-- 직원 테이블 (manager_id가 같은 테이블의 id를 참조)
SELECT e.name AS 직원, m.name AS 매니저
FROM employees e
LEFT JOIN employees m ON e.manager_id = m.id;
-- e와 m 모두 같은 employees 테이블이지만 별칭을 다르게 부여

활용 예시: 계층 구조(조직도, 카테고리 부모-자식 관계) 표현


7. UNION

두 개 이상의 SELECT 결과를 세로로 합치는 연산자입니다.
JOIN이 테이블을 가로로 연결한다면, UNION은 결과를 위아래로 쌓는 개념입니다.

기본 문법

SELECT 컬럼1, 컬럼2 FROM 테이블A
UNION
SELECT 컬럼1, 컬럼2 FROM 테이블B;
-- 컬럼 수와 타입이 일치해야 합니다
-- 예시 데이터
-- tableA: [1, 2, 3]
-- tableB: [2, 3, 4]

SELECT num FROM tableA
UNION
SELECT num FROM tableB;
-- 결과: 1, 2, 3, 4  ← 중복 제거됨

SELECT num FROM tableA
UNION ALL
SELECT num FROM tableB;
-- 결과: 1, 2, 3, 2, 3, 4  ← 중복 그대로

실용 예시 - 이전 FULL OUTER JOIN 대체

-- 왼쪽 기준으로 모두 가져오고
SELECT u.name, o.product
FROM users u
LEFT JOIN orders o ON u.id = o.user_id

UNION  -- 중복 제거하면서 합치기

-- 오른쪽 기준으로 모두 가져오기
SELECT u.name, o.product
FROM users u
RIGHT JOIN orders o ON u.id = o.user_id;

정리

  • JOIN → 테이블을 옆으로 붙이기
  • UNION → 결과를 아래로 쌓기
  • 중복이 필요 없으면 UNION, 성능이 중요하면 UNION ALL
profile
알면 좋은 것보단 잊어버리기 싫은 것들을 기록합니다.

0개의 댓글