목차
- 테이블 정보
- ON A AND B / ON A WHERE B 의 차이점
- LEFT OUTER JOIN시 오른쪽 테이블을 조건에 걸 때
- INNER JOIN으로 풀리는 이유
- ANSI 표준에 (+) 를 사용하면
테이블 정보
- TABLE_A
A NUMBER PK1
C VARCHAR2(20)
- TABLE_B
A NUMBER PK1
C VARCHAR2(20)
- TABLE_C
A NUMBER
D VARCHAR2(20)
ON A AND B / ON A WHERE B 의 차이점
1. 1:1 관계의 테이블 A와 테이블 B
SELECT *
FROM TABLE_A A
LEFT JOIN TABLE_B B
ON A.A = B.A
AND B.A < 6 ;
SELECT *
FROM TABLE_A A
LEFT JOIN TABLE_B B
ON A.A = B.A
WHERE B.A < 6 ;
2. 1:N 관계의 테이블 B와 테이블 C
SELECT *
FROM TABLE_B B
LEFT JOIN TABLE_C C
ON B.A = C.A (+)
AND B.A > 6;
SELECT *
FROM TABLE_B B
LEFT JOIN TABLE_C C
ON B.A = C.A
WHERE B.A > 6;
3. N:1 관계의 테이블 C와 테이블 A
SELECT *
FROM TABLE_C C
LEFT JOIN TABLE_A A
ON C.A = A.A
AND A.A IN (2,6);
SELECT *
FROM TABLE_C C
LEFT JOIN TABLE_A A
ON C.A = A.A
WHERE A.A IN (2,6);
※ 알 수 있는 것
- ON A AND B
--> A랑 B 조건으로 JOIN을 한다.
A와 B 조건에 맞는 데이터만 붙인다. (만족하지 않는 나머지는 NULL)
- ON A WHERE B
--> A 조건으로 JOIN을 한 다음 WHERE B로 거르는 것
LEFT OUTER JOIN시 오른쪽 테이블을 조건에 걸 때
WHERE A = B (+)
AND B = 1
위와 같이 LEFT JOIN시 오른쪽 테이블을 조건에 걸 때,
SELECT *
FROM A, B
WHERE A.a = B.b (+)
AND B.b = 1
→ 위 쿼리는 INNER JOIN으로 풀린다.
SELECT *
FROM A, B
WHERE A.a = B.b (+)
AND B.b(+) = 1
→ OUTER JOIN이 되려면 이렇게 써줘야한다.
예시)
-- INNER JOIN으로 풀리는 쿼리
SELECT *
FROM TABLE_A A,
TABLE_B B
WHERE A.A = B.A (+)
AND B.A < 6;
-- LEFT OUTER JOIN으로 풀리는 쿼리
-- ORACLE
SELECT *
FROM TABLE_A A,
TABLE_B B
WHERE A.A = B.A (+)
AND B.A (+) < 6;
-- ANSI
SELECT *
FROM TABLE_A A
LEFT JOIN TABLE_B B
ON A.A = B.A
AND B.A < 6 ;
+ 왼쪽 테이블 조건
-- ORACLE
SELECT *
FROM TABLE_A A,
TABLE_B B
WHERE A.A = B.A (+)
AND A.A < 6;
-- ANSI
SELECT *
FROM TABLE_A A
LEFT JOIN TABLE_B B
ON A.A = B.A
WHERE A.A < 6 ;
위와 같이 왼쪽 테이블의 조건이 걸리면 그대로 LEFT OUTER JOIN으로 풀린다.
※ 알 수 있는 것
LEFT OUTER JOIN을 할 때
ANSI 기준
오른쪽 테이블의 조건은 ON에 넣고 (ON..AND..)
왼쪽 테이블의 조건은 WHERE에 넣는다.
ORACLE 문법은
오른쪽 테이블의 조건엔 (+) 붙여주기
INNER JOIN으로 풀리는 이유
SELECT *
FROM TABLE_A A,
TABLE_B B
WHERE A.A = B.A (+)
AND B.A > 4 ;
여기서 B.A > 4 는 (+)가 붙지 않아 LEFT JOIN 이후에 실행된다.
→ NULL 값을 제외하고 가져온다.
→ 이럴 때는 오라클이 해당 쿼리를 OUTER JOIN에서 INNER JOIN으로 변환한다.
다시 보면,
-- (ORACLE)
SELECT *
FROM TABLE_A A,
TABLE_B B
WHERE A.A = B.A (+)
AND B.A > 4 ;
-- (ANSI)
SELECT *
FROM TABLE_A A
LEFT JOIN TABLE_B BS
ON A.A = B.A
WHERE B.A > 4 ;
위 쿼리들은 다음과 같은 INNER JOIN으로 변환된다.
-- (ORACLE)
SELECT *
FROM TABLE_A A,
TABLE_B B
WHERE A.A = B.A
AND B.A > 4 ;
-- (ANSI)
SELECT *
FROM TABLE_A A
INNER JOIN TABLE_B B
ON A.A = B.A
AND B.A > 4 ;
참고 : https://whereami80.tistory.com/93
ANSI 표준에 (+) 를 사용하면
-- 잘못된 쿼리
SELECT *
FROM TABLE_A A
LEFT JOIN TABLE_B B
ON A.A = B.A
WHERE B.A(+) < 6 ;
이렇게 쓰면 오류가 난다.
오류 코드: ORA-25156
설명: 이전 방식의 포괄 조인(+)은 ANSI 조인과 함께 사용할 수 없음
원인: 쿼리 블록이 ANSI 스타일 조인을 사용하는 경우 외부 조인 (+)을 지정하기위한 이전 표기법을 사용할 수 없습니다.
조치: 외부 조인을 지정할 때는 ANSI 스타일을 사용하십시오.
→ ANSI는 ANSI끼리 (+)는 (+)끼리 사용해야 한다.
SELECT *
FROM TABLE_A A
LEFT JOIN TABLE_B B
ON A.A = B.A (+)
WHERE A.A < 6 ;
이렇게 사용하는건 오류가 나지는 않으나 (+)가 없어도 결과가 같다.
결론은 ANSI는 ANSI끼리 (+)는 (+)끼리
'Dev > Oracle' 카테고리의 다른 글
[Oracle] 상황별 테이블스페이스 명령어 (0) | 2022.07.05 |
---|---|
[Oracle] MERGE (0) | 2022.06.24 |
[Oracle] 제약조건 (0) | 2022.06.21 |
[Oracle] 인덱스 탐색 방식 (0) | 2022.06.21 |
[Oracle] 결합 인덱스 (0) | 2022.06.21 |
댓글