MySQL에서 데이터를 효과적으로 조회하려면 JOIN을 이해하는 것이 필수다. 특히 INNER JOIN, LEFT JOIN, RIGHT JOIN은 관계형 데이터베이스에서 가장 많이 쓰이는 조인 방식이다.

📌 JOIN이란 무엇인가
JOIN은 두 개 이상의 테이블을 연결하여 하나의 결과 집합으로 만드는 SQL 문법이다. 데이터베이스의 정규화 구조에서는 여러 테이블에 흩어진 데이터를 한 번에 조회할 때 반드시 사용된다.
대표적인 JOIN 종류는 다음과 같다.
- INNER JOIN: 공통된 값이 존재하는 경우만 연결
- LEFT JOIN: 왼쪽 테이블의 모든 데이터를 기준으로 연결
- RIGHT JOIN: 오른쪽 테이블의 모든 데이터를 기준으로 연결
🔍 INNER JOIN – 교집합 조회
INNER JOIN은 두 테이블 간 매칭되는 레코드만 조회한다. 예를 들어 회원 테이블과 주문 테이블이 있을 때, 주문한 회원만 조회할 수 있다.
SELECT u.user_id, u.name, o.order_id, o.amount
FROM users u
INNER JOIN orders o ON u.user_id = o.user_id;
이 쿼리는 주문이 있는 회원만 조회되며, 주문 내역이 없는 회원은 결과에서 제외된다.
🧭 LEFT JOIN – 기준 테이블 유지, 없는 값은 NULL
LEFT JOIN은 왼쪽 테이블의 모든 행을 가져오고, 일치하지 않는 오른쪽 테이블의 값은 NULL로 표시된다. 데이터가 누락되지 않도록 기준 테이블을 유지하면서 부가 정보를 연결할 때 유용하다.
SELECT u.user_id, u.name, o.order_id, o.amount
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id;
이 쿼리는 모든 회원을 가져오며, 주문 내역이 없는 회원은 order_id와 amount가 NULL로 출력된다.
🧭 RIGHT JOIN – 반대 기준의 LEFT JOIN
RIGHT JOIN은 LEFT JOIN과 반대로, 오른쪽 테이블을 기준으로 모든 행을 가져온다.
SELECT u.user_id, u.name, o.order_id, o.amount
FROM users u
RIGHT JOIN orders o ON u.user_id = o.user_id;
주문 테이블을 기준으로, 주문 내역이 존재하는 모든 데이터를 조회하며, 사용자 정보가 없는 경우에는 NULL로 표시된다.
🎯 실제 사용 예제 – 회원과 주문, 카테고리 연결
SELECT u.name AS 회원명,
o.order_id AS 주문번호,
c.category_name AS 카테고리
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id
LEFT JOIN products p ON o.product_id = p.product_id
LEFT JOIN categories c ON p.category_id = c.category_id;
이 쿼리는 회원 → 주문 → 상품 → 카테고리까지 연결하여, 회원별로 어떤 카테고리의 상품을 주문했는지 확인할 수 있다. 중간에 누락된 정보가 있어도 전체 회원 목록을 기준으로 출력된다.
🧠 JOIN을 사용할 때 주의할 점
- 조인 조건이 없으면 카티션 곱(Cartesian Product)가 발생해 엄청난 양의 결과가 출력될 수 있다.
- JOIN 시 NULL값 처리에 주의하자. 특히 LEFT JOIN에서 조건절을 WHERE에 걸면 INNER JOIN처럼 동작할 수 있다.
- 성능 향상을 위해 JOIN 대상 컬럼에 인덱스를 설정하는 것이 좋다.
💡 JOIN과 서브쿼리 차이
JOIN은 두 테이블을 나란히 펼쳐 놓고 조건으로 연결하는 반면, 서브쿼리는 하나의 결과를 먼저 구한 뒤 그 결과를 다른 쿼리에 넣는다. JOIN은 다량의 데이터 집계를 처리할 때 훨씬 효율적이다.
📘 공식 문서 참고 링크
'DB' 카테고리의 다른 글
| [MySQL] LIKE와 REGEXP 차이부터 고급 패턴 검색까지 완벽 정리 (0) | 2025.06.26 |
|---|---|
| [MySQL] IS NULL과 IS NOT NULL 완전 정복! 조건절로 놓치지 말아야 할 핵심 포인트 (2) | 2025.06.26 |
| [MySQL] SELECT 문에서 EXISTS와 IN 조건절 (1) | 2025.06.26 |
| [MySQL] SELECT + 서브쿼리 활용법 (쿼리 안에 쿼리) (0) | 2025.06.26 |
| [MySQL] SELECT + DATE_FORMAT / NOW() 함수 완벽 정리(날짜포맷, 현재시간) (0) | 2025.06.25 |
| [MySQL] SELECT CASE / IF 조건 분기 (쿼리 조건문 활용) (0) | 2025.06.25 |
| [MySQL] SELECT + COUNT, SUM, AVG, MAX, MIN 집계 함수 완전 정복 (0) | 2025.06.25 |
| [MySQL] SELECT DISTINCT – 중복된 데이터 없이 깔끔하게 조회하는 법 (0) | 2025.06.25 |