두 테이블의 모든 행을 포함하는 JOIN을 제공하며, 매칭되지 않는 행은 NULL로 채움
-- 테이블 데이터 예시
-- customer: (id=1, name='김철수'), (id=2, name='이영희'), (id=3, name='박민수')
-- orders: (cust_id=1, order_date='2025-01-01'), (cust_id=2, order_date='2025-01-02'), (cust_id=4, order_date='2025-01-03')
SELECT
c.id AS cust_id
, c.name
, o.order_date
FROM customer c
FULL OUTER JOIN orders o
ON c.id = o.cust_id;
| cust_id | name | order_date |
|---|---|---|
| 1 | 김철수 | 2025-01-01 |
| 2 | 이영희 | 2025-01-02 |
| 3 | 박민수 | NULL |
| NULL | NULL | 2025-01-03 |
SELECT
c.id AS cust_id
, c.name
, o.order_date
FROM customer c
LEFT JOIN orders o
ON c.id = o.cust_id
UNION
SELECT
c.id AS cust_id
, c.name
, o.order_date
FROM customer c
RIGHT JOIN orders o
ON c.id = o.cust_id
단, 위 방법은 두 번의 JOIN을 수행하므로 주의가 필요
성능을 크게 높이는 방법은 없지만 다음과 같이 개선 시킬 수 있다.
1) 서브쿼리를 이용한 배타적 합집합 (성능 최적화) - 성능 중심
-- 모든 왼쪽 데이터 + 교집합
SELECT
c.id AS cust_id
, c.name
, o.order_date
FROM customer c
LEFT JOIN orders o
ON c.id = o.cust_id
UNION ALL -- 중복 체크를 하지 않는 UNION ALL을 써서 비용 절감
-- 오른쪽 테이블에만 존재하는 데이터 (교집합 제외)
SELECT
o.cust_id
, c.name
, o.order_date
FROM customer c
RIGHT JOIN orders o
ON c.id = o.cust_id
WHERE c.id IS NULL; -- 이미 위에서 나온 데이터는 제외
2) 집계 함수를 이용한 방식 - 테이블이 여러 개인 경우 연산량 감소
SELECT
cust_id
, MAX(name) AS name
, MAX(order_date) AS order_date
FROM (
-- customer 테이블 데이터 준비
SELECT id AS cust_id
, name
, NULL AS order_date
FROM customer
UNION ALL
-- orders 테이블 데이터 준비
SELECT cust_id
, NULL AS name
, order_date
FROM orders
) AS combined
GROUP BY cust_id;
자기 자신을 JOIN하는 방식으로 계층 구조나 자기 참조 데이터에 유용
SELECT e1.name
, e2.name
FROM employees e1
JOIN employees e2
ON e1.manager_id = e2.id;
두 테이블의 동일한 이름과 데이터 타입을 가진 컬럼을 자동으로 찾아 동등 JOIN
ON 조건 없이도 연결됨SELECT *
FROM customers NATURAL JOIN cities;
왼쪽 테이블에서 오른쪽 테이블에 존재하는 행만 반환하며, 오른쪽 컬럼은 결과에 포함하지 않음
EXIST나 IN 연산자 사용-- EXISTS 사용
SELECT *
FROM Customers c
WHERE EXISTS (
SELECT 1
FROM Orders o
WHERE o.customer_id = c.id
);
-- IN 사용
SELECT *
FROM Customers
WHERE id IN (
SELECT customer_id
FROM Orders
);
ex. 한 명의 고객이 100번 주문한다면
DISTINCT 필요)INNER JOIN + DISTINCT 사용하는 것보다 빠를때가 많음.왼쪽 테이블에서 오른쪽 테이블에 일치하는 행이 없는 데이터만 반환하는 JOIN 기법.
<=> SEMI JOIN
NOT EXISTS나 NOT IN 연산자를 사용-- NOT EXISTS 사용
SELECT *
FROM Customers c
WHERE NOT EXISTS (
SELECT 1
FROM Orders o
WHERE o.customer_id = c.id
);
-- NOT IN 사용
SELECT *
FROM Customers
WHERE id NOT IN (
SELECT customer_id
FROM Orders
);
-- LEFT JOIN + NULL 체크
SELECT c.*
FROM Customers c
LEFT JOIN Orders o
ON c.id = o.customer_id
WHERE o.customer_id IS NULL;
NOT IN사용 시 오른쪽 테이블에NULL이 있으면 전체 결과가 누락될 수 있음.