본문 바로가기

표준 조인, INNER·OUTER·CROSS JOIN

DB SorryP 2026. 10. 8. 18:19
반응형

SQLD 2과목의 「표준 조인」 항목을 정리합니다. FROM 절에 JOIN 키워드로 조인을 쓰는 표준 조인 문법, INNER JOIN과 ON 절, USING과 NATURAL JOIN의 규칙, CROSS JOIN, LEFT·RIGHT·FULL OUTER JOIN의 결과와 행 수 계산, OUTER JOIN에서 조건을 ON에 둘 때와 WHERE에 둘 때의 차이, 여러 테이블 OUTER JOIN, 오라클 (+) 표기를 표준 조인으로 바꿔 쓰는 방법, SQL Server와의 차이를 쇼핑몰 예시로 살펴본 뒤 기출 유형 연습 문제 5개로 확인합니다.

앞 글 「조인 기초, 등가 조인과 오라클 (+) 표기」에서 WHERE 절에 조인 조건을 쓰는 방식과 오라클 (+) 아우터 조인을 정리했습니다. 이번에는 같은 조인을 FROM 절에 JOIN 키워드로 쓰는 표준 조인(ANSI/ISO SQL 표준)을 다룹니다. 시험에는 표준 조인의 결과 행 수를 세는 문제, NATURAL JOIN과 USING의 문법 오류를 고르는 문제, (+) 표기와 같은 결과를 내는 표준 조인을 고르는 문제가 자주 나옵니다. 예시 데이터는 앞 글과 같은 쇼핑몰 다섯 테이블과 가격대, 쿠폰 테이블입니다. 연습 문제는 실제 시험과 같은 유형으로 새로 만든 문제입니다.

1. 표준 조인 한눈에 보기

벤 다이어그램 액자 다섯 개. 고객 5명과 쿠폰 3장에서 INNER 2행, LEFT 5행, RIGHT 3행, FULL 6행, CROSS 15행. 선배가 FULL은 5 + 3 - 2라고 설명하고 초보와 모자 친구가 행 수 스티커를 듭니다

표준 조인은 조인 종류와 조인 조건을 FROM 절에 씁니다.

SELECT ... FROM A [INNER] JOIN B ON 조인조건;
SELECT ... FROM A JOIN B USING (같은이름컬럼);
SELECT ... FROM A NATURAL JOIN B;
SELECT ... FROM A CROSS JOIN B;
SELECT ... FROM A LEFT [OUTER] JOIN B ON 조인조건;
SELECT ... FROM A RIGHT [OUTER] JOIN B ON 조인조건;
SELECT ... FROM A FULL [OUTER] JOIN B ON 조인조건;
종류 결과 쇼핑몰 예
INNER JOIN 양쪽에 짝이 있는 행만 고객-주문 7행
USING 지정한 같은 이름 컬럼으로 등가 조인 고객-주문 7행
NATURAL JOIN 이름이 같은 모든 컬럼으로 등가 조인 고객-주문 7행
CROSS JOIN 카티션 곱(조건 없음) 등급 3 × 가격대 4 = 12행
LEFT OUTER JOIN 왼쪽 전부, 짝이 없으면 오른쪽은 NULL 고객-주문 8행(C05는 NULL)
RIGHT OUTER JOIN 오른쪽 전부, 짝이 없으면 왼쪽은 NULL 주문상품-상품 12행(P40은 NULL)
FULL OUTER JOIN 양쪽 전부, 짝이 없으면 반대쪽은 NULL 고객-쿠폰 6행
  • INNER와 OUTER는 생략할 수 있습니다. JOIN만 쓰면 INNER JOIN, LEFT JOIN은 LEFT OUTER JOIN, FULL JOIN은 FULL OUTER JOIN입니다.
  • 표준 조인은 조인 조건은 FROM 절(ON, USING)에, 행을 거르는 조건은 WHERE 절에 두어 둘을 나눠 볼 수 있다는 것이 장점입니다.

2. INNER JOIN과 ON

주문, 고객, 등급 객차가 ON 연결고리로 이어진 기차와 G 등급 주문 5001 김하나 골드, 5003 김하나 골드, 5006 최네오 골드 표. 연결고리 없이 붙이면 ON 또는 USING 필요 오류 ORA-02000이 나고 도우미 로봇이 연결고리를 건넵니다

앞 글에서 WHERE 절로 쓴 주문-고객-등급 조인을 INNER JOIN으로 바꾸면 다음과 같습니다.

SELECT o.주문번호, c.고객명, g.등급명
  FROM 주문 o
  INNER JOIN 고객 c ON o.고객번호 = c.고객번호
  INNER JOIN 등급 g ON c.등급코드 = g.등급코드
 WHERE g.등급코드 = 'G'
 ORDER BY o.주문번호;
주문번호 고객명 등급명
5001 김하나 골드
5003 김하나 골드
5006 최네오 골드
  • ON에는 =뿐 아니라 비등가 조건도 쓸 수 있습니다. 상품 p JOIN 가격대 g ON p.판매가 BETWEEN g.최저가 AND g.최고가는 앞 글과 같은 6행입니다.
  • INNER JOIN에서 ON(또는 USING)을 빼면 오류입니다. FROM 고객 c INNER JOIN 주문 o만 쓰면 ORA-02000(ON 또는 USING 키워드 누락)입니다.
  • INNER JOIN에서는 일반 조건(c.등급코드 = 'G')을 ON에 두든 WHERE에 두든 결과가 같습니다(둘 다 3행). OUTER JOIN에서는 달라지는데, 6장에서 봅니다.

3. USING과 NATURAL JOIN

고객과 주문이 함께 가진 고객번호 카드. 초보가 c. 이름표를 붙이려 하자 로봇이 공동 소유라 이름표 금지 팻말과 ORA-25154를 듭니다. USING과 NATURAL 비교표, 같은 이름 컬럼이 없는 상품과 등급의 NATURAL JOIN은 6 × 3 = 18행

USING과 NATURAL JOIN은 이름이 같은 컬럼으로 등가 조인합니다. USING은 괄호 안에 조인할 컬럼을 직접 적고, NATURAL JOIN은 두 테이블에서 이름이 같은 모든 컬럼을 알아서 찾습니다.

SELECT 고객번호, c.고객명, o.주문번호
  FROM 고객 c JOIN 주문 o USING (고객번호);

SELECT 고객번호, c.고객명, o.주문번호
  FROM 고객 c NATURAL JOIN 주문 o;

두 SQL 모두 고객-주문 7행입니다. 고객과 주문에 같은 이름의 컬럼은 고객번호 하나뿐이라 결과가 같습니다.

항목 USING NATURAL JOIN
조인 컬럼 괄호 안에 지정한 컬럼 이름이 같은 모든 컬럼
조건 종류 등가 조인만 등가 조인만
조인 컬럼에 별칭·테이블명 불가(ORA-25154) 불가(ORA-25155)
조인 컬럼이 아닌 컬럼 별칭 사용 가능 별칭 사용 가능
ON과 함께 쓰기 불가 불가(ORA-03048)
SELECT *의 공통 컬럼 맨 앞에 한 번만 맨 앞에 한 번만
SQL Server 지원 안 함 지원 안 함

가장 자주 나오는 것은 셋째 줄입니다. USING이나 NATURAL JOIN에 쓰인 조인 컬럼은 어느 한 테이블의 것이 아니라 두 테이블이 함께 쓰는 컬럼이 되므로 접두사를 붙일 수 없습니다.

-- 오류(ORA-25154): USING 조인 컬럼에 별칭을 붙임
SELECT c.고객번호, c.고객명
  FROM 고객 c JOIN 주문 o USING (고객번호);

SELECT *의 컬럼 순서

SELECT * FROM 등급 g JOIN 고객 c USING (등급코드);
SELECT * FROM 등급 NATURAL JOIN 고객;
SELECT * FROM 등급 g JOIN 고객 c ON g.등급코드 = c.등급코드;
조인 결과 컬럼
USING 등급코드, 등급명, 할인율, 고객번호, 고객명, 휴대폰번호, 이메일
NATURAL JOIN 등급코드, 등급명, 할인율, 고객번호, 고객명, 휴대폰번호, 이메일
ON 등급코드, 등급명, 할인율, 고객번호, 고객명, 휴대폰번호, 이메일, 등급코드
  • 고객 테이블의 마지막 컬럼이던 등급코드가 USING과 NATURAL JOIN에서는 맨 앞으로 와서 한 번만 나옵니다. ON은 두 테이블의 컬럼을 모두 보여 주므로 등급코드가 두 번 나옵니다.
  • 같은 이름의 컬럼이 하나도 없는 상품 NATURAL JOIN 등급은 오류가 아니라 6 × 3 = 18행, 즉 카티션 곱이 됩니다.
  • 같은 이름의 컬럼이 둘 이상이면(예: 두 테이블 모두에 「등록일」이 있는 경우) NATURAL JOIN은 의도하지 않은 컬럼까지 조건에 넣습니다. 그래서 실무에서는 조인 컬럼을 직접 적는 ON이나 USING을 더 많이 씁니다.

4. CROSS JOIN

등급 3줄과 가격대 4칸으로 된 12칸 조합표. 모자 친구가 스티커 12장을 들고, 초보의 ON 스티커는 막히며 CROSS JOIN에 ON을 쓰면 ORA-03048. 선배가 CROSS는 조건 없이 모든 조합이라고 말합니다

SELECT g.등급명, p.가격대명
  FROM 등급 g CROSS JOIN 가격대 p;
  • 등급 3행 × 가격대 4행 = 12행입니다. 「등급별·가격대별 판매 실적표의 빈칸까지 모두 만들기」처럼 모든 조합이 필요할 때 씁니다.
  • FROM 등급 g, 가격대 p처럼 조건 없이 쉼표로 나열한 것과 같습니다.
  • CROSS JOIN에는 ON을 붙일 수 없습니다(ORA-03048).

5. OUTER JOIN 세 가지와 행 수

LEFT 결과 카드 5장과 RIGHT 결과 카드 3장에서 같은 카드 2장이 합쳐져 FULL 6장이 됩니다. 칠판에 5 + 3 - 2 = 6, 단순 합 8은 틀림. 초보가 RIGHT와 FULL에만 있는 NULL-K03 카드를 들고 있습니다

고객(5행)과 쿠폰(3행, K03은 고객번호 NULL)을 c.고객번호 = k.고객번호로 이어 보겠습니다.

SELECT c.고객번호, c.고객명, k.쿠폰번호, k.쿠폰명
  FROM 고객 c FULL OUTER JOIN 쿠폰 k
    ON c.고객번호 = k.고객번호
 ORDER BY c.고객번호, k.쿠폰번호;
고객번호 고객명 쿠폰번호 쿠폰명
C01 김하나 K01 여름_10%할인
C02 이두리 NULL NULL
C03 박세미 K02 여름10할인
C04 최네오 NULL NULL
C05 정다솜 NULL NULL
NULL NULL K03 가을_5%할인

FULL 자리에 다른 조인을 넣으면 행 수가 다음과 같습니다.

조인 행 수 결과
INNER 2 C01-K01, C03-K02
LEFT(고객 기준) 5 위 2행 + C02, C04, C05(쿠폰 NULL)
RIGHT(쿠폰 기준) 3 위 2행 + K03(고객 NULL)
FULL 6 위 2행 + C02, C04, C05 + K03
CROSS 15 5 × 3
  • FULL OUTER JOIN은 LEFT와 RIGHT 결과의 합집합(UNION)입니다. LEFT 5행과 RIGHT 3행에서 겹치는 2행이 한 번만 남아 6행입니다. 행 수는 LEFT + RIGHT - INNER = 5 + 3 - 2 = 6이고, 단순히 더한 8이 아닙니다.
  • A LEFT JOIN B와 B RIGHT JOIN A는 같습니다. 고객 LEFT JOIN 주문과 주문 RIGHT JOIN 고객은 둘 다 8행입니다.
  • K03은 고객번호가 NULL이라 어떤 고객과도 짝이 되지 않습니다. 그래서 쿠폰을 모두 남기는 RIGHT와 FULL에서만 보입니다.

6. OUTER JOIN에서 ON 조건과 WHERE 조건

10월 5일 이후 날짜 조건을 ON에 두면 고객 5명이 모두 남고 C01과 C05는 NULL 풍선을 받아 5행. WHERE에 두면 NULL 두 명이 출구에서 걸러져 3행. 왼쪽 테이블 조건은 ON에서 6행, WHERE에서 3행

INNER JOIN에서는 같았던 ON과 WHERE가 OUTER JOIN에서는 결과를 바꿉니다.

-- (가) 날짜 조건을 ON에
SELECT c.고객번호, o.주문번호
  FROM 고객 c LEFT OUTER JOIN 주문 o
    ON c.고객번호 = o.고객번호
   AND o.주문일시 >= DATE '2026-10-05';

-- (나) 날짜 조건을 WHERE에
SELECT c.고객번호, o.주문번호
  FROM 고객 c LEFT OUTER JOIN 주문 o
    ON c.고객번호 = o.고객번호
 WHERE o.주문일시 >= DATE '2026-10-05';
조건 위치 결과
(가) 오른쪽 테이블 조건을 ON에 5행: C01 NULL, C02 5005, C03 5007, C04 5006, C05 NULL
(나) 오른쪽 테이블 조건을 WHERE에 3행: C02 5005, C03 5007, C04 5006
(다) 왼쪽 테이블 조건 c.등급코드 = 'G'를 ON에 6행: C01(5001, 5003)과 C04(5006)만 주문이 붙고, C02·C03·C05는 주문 NULL로 남음
(라) 왼쪽 테이블 조건 c.등급코드 = 'G'를 WHERE에 3행: 5001, 5003, 5006
  • ON 조건은 「어떤 행끼리 짝을 지을지」만 정합니다. LEFT JOIN의 왼쪽 행은 ON 조건이 거짓이어도 사라지지 않고, 짝이 없는 행으로 남습니다. 그래서 (다)는 고객 5명이 모두 남습니다.
  • WHERE 조건은 조인이 끝난 결과를 거릅니다. (나)에서 NULL로 채운 C01, C05 행은 o.주문일시 >= …에서 UNKNOWN이 되어 빠지므로 결과적으로 INNER JOIN과 같아집니다.
  • 앞 글의 「상수 조건에 (+)가 없음」과 같은 현상입니다. 날짜 조건을 ON에 넣은 (가)가 「상수 조건에도 (+)」를 붙인 SQL과 같은 결과(5행)입니다.

7. 여러 테이블 OUTER JOIN

릴레이 경주. 두 번째 문이 INNER면 주문이 없는 C05가 막혀 11행, 두 번째 문도 LEFT면 C05가 NULL NULL로 결승해 12행. 모자 친구가 중계석에서 끝까지 LEFT라고 외칩니다

고객 전부와 주문, 주문상품을 이어 보겠습니다.

-- (가) 두 번째 조인도 LEFT: 12행, 마지막 행이 C05 NULL NULL
SELECT c.고객번호, o.주문번호, oi.상품번호
  FROM 고객 c
  LEFT JOIN 주문 o ON c.고객번호 = o.고객번호
  LEFT JOIN 주문상품 oi ON o.주문번호 = oi.주문번호;

-- (나) 두 번째 조인이 INNER: 11행, C05가 사라짐
SELECT c.고객번호, o.주문번호, oi.상품번호
  FROM 고객 c
  LEFT JOIN 주문 o ON c.고객번호 = o.고객번호
  JOIN 주문상품 oi ON o.주문번호 = oi.주문번호;

(나)에서는 앞의 LEFT JOIN으로 살린 C05 행의 주문번호가 NULL이라, 뒤의 INNER JOIN 조건 o.주문번호 = oi.주문번호에서 짝을 찾지 못해 빠집니다. 앞 글에서 본 「(+)를 일부 조건에 빠뜨림」(11행)과 같습니다. 살린 행을 끝까지 남기려면 이어지는 조인도 LEFT로 씁니다.

짝이 없는 행만 찾기

SELECT c.고객번호, c.고객명
  FROM 고객 c LEFT JOIN 주문 o
    ON c.고객번호 = o.고객번호
 WHERE o.주문번호 IS NULL;

결과는 C05 정다솜 1행입니다. 「주문이 없는 고객」은 뒤의 글에서 NOT EXISTS와 MINUS로도 같은 답을 구해 봅니다.

8. (+) 표기를 표준 조인으로 바꾸기

(+)가 없는 쪽이 주인공이라고 적힌 번역기. o.고객번호(+)는 고객 LEFT JOIN 주문 8행, oi.상품번호(+)는 주문상품 RIGHT JOIN 상품 12행. 상수 조건과 양쪽 (+)까지 정리한 변환표

-- 오라클 (+) 표기: 8행
SELECT c.고객번호, o.주문번호
  FROM 고객 c, 주문 o
 WHERE c.고객번호 = o.고객번호(+);

-- 표준 조인: 같은 8행
SELECT c.고객번호, o.주문번호
  FROM 고객 c LEFT OUTER JOIN 주문 o
    ON c.고객번호 = o.고객번호;
(+) 표기 표준 조인과 결과
주문 쪽에 (+), o.고객번호(+) 고객 LEFT JOIN 주문, 8행
고객 쪽에 (+), c.고객번호(+) 고객 RIGHT JOIN 주문, 7행
주문상품 쪽에 (+), oi.상품번호(+) 주문상품 RIGHT JOIN 상품, 12행
상수 조건에도 (+) 상수 조건을 ON으로, 5행
상수 조건에 (+) 없음 상수 조건을 WHERE로, 3행
양쪽에 (+)는 불가 FULL OUTER JOIN, 고객-쿠폰 6행

바꿔 쓰는 요령은 다음과 같습니다.

  • (+)가 없는 쪽이 기준, 즉 모두 남는 쪽입니다. FROM 절에서 기준 테이블을 왼쪽에 두면 LEFT, 오른쪽에 두면 RIGHT입니다.
  • FROM 주문상품 oi, 상품 p WHERE oi.상품번호(+) = p.상품번호는 상품이 기준이고 상품이 FROM 절 오른쪽에 있으므로 RIGHT OUTER JOIN입니다. LEFT로 바꾸면 주문상품 기준이 되어 11행입니다.
  • (+)가 붙은 상수 조건은 ON으로, (+)가 없는 조건은 WHERE로 옮깁니다.
  • NATURAL LEFT JOIN도 쓸 수 있지만(고객 NATURAL LEFT JOIN 주문은 8행) 시험에는 거의 나오지 않습니다.

9. SQL Server와의 차이

오라클 공구함에는 NATURAL, USING, (+)가 있고 SQL Server 공구함의 같은 자리는 문법 오류. 공통 공구 INNER, LEFT, RIGHT, FULL, CROSS를 로봇이 모읍니다. 오름차순 정렬의 NULL은 오라클 맨 뒤, SQL Server 맨 앞

항목 오라클 SQL Server
INNER, LEFT, RIGHT, FULL, CROSS 지원 지원(결과 같음)
NATURAL JOIN 지원 문법 오류
USING 지원 문법 오류
(+) 지원 문법 오류
오름차순 정렬에서 NULL 맨 뒤 맨 앞
  • SQL Server의 FROM 절 조인은 INNER, LEFT·RIGHT·FULL OUTER, CROSS JOIN이고 NATURAL JOIN과 USING이 없습니다. 「SQL Server는 NATURAL JOIN과 USING을 지원하지 않는다」는 보기가 자주 나옵니다.
  • FULL OUTER JOIN 결과를 ORDER BY로 정렬하면 NULL의 위치가 다릅니다. 「WHERE 절과 ORDER BY, Top N 쿼리」에서 본 NULL 정렬 차이와 같습니다.

10. 헷갈리기 쉬운 점

허들 다섯 개에 USING 컬럼 접두사 금지, NATURAL은 같은 이름 모든 컬럼, FULL은 LEFT 더하기 RIGHT가 아님, OUTER에서 WHERE는 NULL을 거름, LEFT 뒤 INNER 주의가 붙어 있고 초보가 FULL 허들 앞에서 당황합니다. 선배는 결승선에서 응원합니다

  • USING과 NATURAL JOIN의 조인 컬럼에는 접두사를 붙이지 않습니다. c.고객번호가 아니라 고객번호라고 씁니다. 조인 컬럼이 아닌 컬럼(c.고객명)에는 붙여도 됩니다.
  • NATURAL JOIN은 이름이 같은 「모든」 컬럼으로 조인합니다. 같은 이름의 컬럼이 없으면 오류가 아니라 카티션 곱입니다.
  • FULL OUTER JOIN의 행 수는 LEFT + RIGHT가 아닙니다. 양쪽 모두에 짝이 있는 행(INNER 결과)이 두 번 세어지므로 한 번 빼야 합니다. FULL은 LEFT와 RIGHT를 UNION ALL이 아니라 UNION한 것과 같습니다.
  • OUTER JOIN에서 ON과 WHERE는 다릅니다. 오른쪽 테이블 조건을 WHERE에 두면 NULL 행이 걸러져 INNER JOIN처럼 되고, 왼쪽 테이블 조건을 ON에 두면 왼쪽 행은 줄지 않습니다.
  • LEFT JOIN 다음의 INNER JOIN은 살린 행을 다시 지울 수 있습니다. 이어지는 조인도 LEFT로 써야 C05 같은 행이 남습니다.
  • (+)를 표준 조인으로 바꿀 때는 (+)가 없는 테이블이 기준입니다. 기준 테이블이 왼쪽이면 LEFT, 오른쪽이면 RIGHT입니다.
  • INNER JOIN에는 ON이나 USING이 꼭 필요하고, CROSS JOIN과 NATURAL JOIN에는 ON을 쓸 수 없습니다.
  • 조인 컬럼이 NULL인 행은 INNER JOIN에서 빠지고 OUTER JOIN에서만 남습니다. 쿠폰 K03은 RIGHT와 FULL에서만 보입니다.

11. 연습 문제

기차역 전광판에 문제 5개가 떠 있고 초보, 모자 친구, 로봇이 줄을 섭니다. 선배가 다음 역 서브쿼리 안내판 옆에 서 있습니다. 문제 5개, 풀이는 아래에

표준 조인의 결과 행 수와 문법 규칙, (+) 표기와의 관계를 확인하는 문제입니다. 실제 시험과 같은 유형으로 새로 만들었습니다. 정답과 풀이는 다음 장에 있으니, 먼저 직접 풀어 보세요.

문제 1에서 쓰는 두 테이블은 다음과 같습니다.

[고객]

고객번호 고객명
C01 김하나
C02 이두리
C03 박세미
C04 최네오
C05 정다솜

[쿠폰]

쿠폰번호 고객번호
K01 C01
K02 C03
K03 NULL

문제 1. 다음 네 SQL의 결과 행 수를 (가)부터 차례대로 바르게 나열한 것은?

(가) SELECT * FROM 고객 c INNER JOIN 쿠폰 k ON c.고객번호 = k.고객번호;
(나) SELECT * FROM 고객 c LEFT OUTER JOIN 쿠폰 k ON c.고객번호 = k.고객번호;
(다) SELECT * FROM 고객 c RIGHT OUTER JOIN 쿠폰 k ON c.고객번호 = k.고객번호;
(라) SELECT * FROM 고객 c FULL OUTER JOIN 쿠폰 k ON c.고객번호 = k.고객번호;

① 2, 5, 3, 8
② 3, 5, 3, 6
③ 2, 5, 2, 5
④ 2, 5, 3, 6

문제 2. 주문 테이블에도 고객번호 컬럼이 있다. 오라클 기준으로 오류가 발생하는 SQL은?
① SELECT 고객번호, c.고객명 FROM 고객 c JOIN 주문 o USING (고객번호);
② SELECT 고객번호, o.주문번호 FROM 고객 c NATURAL JOIN 주문 o;
③ SELECT c.고객번호, c.고객명 FROM 고객 c JOIN 주문 o USING (고객번호);
④ SELECT c.고객번호, o.주문번호 FROM 고객 c JOIN 주문 o ON c.고객번호 = o.고객번호;

문제 3. [주문] 테이블이 다음과 같고, 고객 테이블에는 C01~C05 다섯 명이 있다. 두 SQL의 결과 행 수를 차례대로 고른 것은?

주문번호 고객번호 주문일시
5001 C01 2026-10-01
5002 C02 2026-10-02
5003 C01 2026-10-03
5004 C03 2026-10-04
5005 C02 2026-10-05
5006 C04 2026-10-06
5007 C03 2026-10-07
(가) SELECT c.고객번호, o.주문번호
       FROM 고객 c LEFT OUTER JOIN 주문 o
         ON c.고객번호 = o.고객번호 AND o.주문일시 >= DATE '2026-10-05';
(나) SELECT c.고객번호, o.주문번호
       FROM 고객 c LEFT OUTER JOIN 주문 o
         ON c.고객번호 = o.고객번호
      WHERE o.주문일시 >= DATE '2026-10-05';

① 5, 3
② 5, 5
③ 3, 3
④ 8, 3

문제 4. 다음 오라클 SQL과 결과가 같은 SQL은? (상품은 6개이고, 그중 P40은 주문상품에 한 번도 나오지 않는다.)

SELECT p.상품번호, oi.주문번호
  FROM 주문상품 oi, 상품 p
 WHERE oi.상품번호(+) = p.상품번호;

① SELECT p.상품번호, oi.주문번호 FROM 주문상품 oi LEFT OUTER JOIN 상품 p ON oi.상품번호 = p.상품번호;
② SELECT p.상품번호, oi.주문번호 FROM 주문상품 oi RIGHT OUTER JOIN 상품 p ON oi.상품번호 = p.상품번호;
③ SELECT p.상품번호, oi.주문번호 FROM 주문상품 oi INNER JOIN 상품 p ON oi.상품번호 = p.상품번호;
④ SELECT p.상품번호, oi.주문번호 FROM 주문상품 oi FULL OUTER JOIN 상품 p ON oi.상품번호(+) = p.상품번호;

문제 5. 표준 조인에 대한 설명으로 가장 적절하지 않은 것은?
① NATURAL JOIN은 두 테이블에서 이름이 같은 모든 컬럼으로 등가 조인한다.
② CROSS JOIN은 조인 조건 없이 두 테이블의 모든 행을 조합한다.
③ FULL OUTER JOIN의 결과 행 수는 항상 LEFT OUTER JOIN 행 수와 RIGHT OUTER JOIN 행 수를 더한 값이다.
④ SQL Server는 USING 절을 지원하지 않는다.

12. 풀이

문제 1. 정답 ④
INNER는 짝이 있는 C01-K01, C03-K02의 2행입니다. LEFT는 고객 5명 전부라 5행, RIGHT는 쿠폰 3장 전부라 3행입니다(K03은 고객번호가 NULL이라 짝이 없음). FULL은 LEFT + RIGHT - INNER = 5 + 3 - 2 = 6행입니다. ①은 FULL을 단순히 더한 값, ③은 K03을 빠뜨린 값입니다.

문제 2. 정답 ③
USING에 쓴 조인 컬럼(고객번호)에는 테이블 별칭을 붙일 수 없습니다(ORA-25154). ①은 조인 컬럼에 접두사가 없고 다른 컬럼에만 붙였으므로 실행됩니다. ②도 NATURAL JOIN의 공통 컬럼에 접두사가 없어 실행되고(7행), ④는 ON이라 오히려 접두사가 필요합니다.

문제 3. 정답 ①
(가)는 날짜 조건이 ON에 있어 「짝 짓기 조건」으로만 쓰이므로 고객 5명이 모두 남습니다(C01, C05는 주문 NULL). (나)는 조인 뒤 WHERE에서 NULL 행과 10월 5일 이전 주문이 걸러져 5005, 5006, 5007의 3행만 남습니다. ④의 8은 날짜 조건이 없을 때의 LEFT JOIN 행 수입니다.

문제 4. 정답 ②
(+)가 주문상품 쪽에 있으므로 주문상품이 NULL로 채워지는 쪽이고, 상품이 모두 남습니다. FROM 절 오른쪽에 있는 상품을 모두 남기는 RIGHT OUTER JOIN입니다(12행, P40은 주문번호 NULL). ①은 주문상품 기준이라 11행, ③도 11행이고, ④는 표준 조인 안에 (+)를 섞어 오류(ORA-25156)입니다.

문제 5. 정답 ③
FULL OUTER JOIN의 행 수는 LEFT + RIGHT - INNER입니다. 문제 1처럼 5 + 3 = 8이 아니라 6입니다.

마치며

이번 글에서는 FROM 절에 쓰는 표준 조인을 정리했습니다.

  • INNER JOIN은 ON(또는 USING)이 꼭 필요하고, INNER와 OUTER는 생략할 수 있습니다.
  • USING과 NATURAL JOIN은 같은 이름 컬럼으로 등가 조인하며, 조인 컬럼에는 별칭을 붙일 수 없습니다. SELECT *에서 공통 컬럼은 맨 앞에 한 번만 나옵니다.
  • 같은 이름 컬럼이 없는 NATURAL JOIN과 CROSS JOIN은 카티션 곱입니다. 예시에서 등급 × 가격대는 12행입니다.
  • 고객-쿠폰 예시에서 INNER 2, LEFT 5, RIGHT 3, FULL 6, CROSS 15행입니다. FULL은 LEFT + RIGHT - INNER입니다.
  • OUTER JOIN에서 오른쪽 테이블 조건을 WHERE에 두면 INNER JOIN처럼 되고, ON에 두면 왼쪽 행이 모두 남습니다.
  • (+) 표기를 바꿀 때는 (+)가 없는 테이블이 기준입니다. SQL Server는 NATURAL JOIN, USING, (+)를 지원하지 않습니다.

다음 글 「서브쿼리 종류와 NOT IN의 NULL 함정」에서는 SQL 안에 SQL을 넣는 서브쿼리를 다룹니다. 스칼라 서브쿼리와 인라인 뷰, 단일행·다중행 서브쿼리와 ANY·ALL·EXISTS, NOT IN과 NULL의 함정, 연관 서브쿼리와 뷰를 쇼핑몰 예시로 살펴보고 기출 유형 문제로 확인합니다.

참고 자료(공식)

반응형