"설명을 앞서 예시로 사용할 테이블은 아래와 같다."
IN/NOT IN
SELECT *
FROM EMPLOYEE A
WHERE A.DEPT_CD IN (SELECT DEPT_CD
FROM DEPT);
SELECT *
FROM EMPLOYEE A
WHERE A.DEPT_CD IN ('001', '002', '003', '004');
SELECT *
FROM DEPT A
WHERE A.DEPT_CD IN (SELECT DEPT_CD
FROM EMPLOYEE);
SELECT *
FROM DEPT A
WHERE A.DEPT_CD IN ('001', '002', '003', '004');
드라이빙 테이블이 EMPLOYEE일 때의 결과
드라이빙 테이블이 DEPT일 때의 결과
IN안에 있는 sql문이 OR연산을 한다는 것을 결과만 봐도 알 수 있을 것이다.
-- 1
SELECT *
FROM EMPLOYEE A
WHERE A.DEPT_CD NOT IN (SELECT DEPT_CD
FROM DEPT);
-- 2
SELECT *
FROM EMPLOYEE A
WHERE A.DEPT_CD NOT IN ('001', '002', '003', '004');
-- 3
SELECT *
FROM DEPT A
WHERE A.DEPT_CD NOT IN (SELECT DEPT_CD
FROM EMPLOYEE);
-- 4
SELECT *
FROM DEPT A
WHERE A.DEPT_CD NOT IN ('001', '002', '003', '004');
1~3번의 결과는 아래와 같다.
4번의 SQL문 결과는 아래와 같다.
NOT IN구문일 경우, AND 연산이 된다는 것을 결과를 보면 확인할 수 있다.
3번 sql문을 예시로 들면 NOT IN구문인 서브쿼리를 본다면 EMPLOYEE안에 있는 DEPT_CD는 아래와 같다.
즉, 001, 002, 003, 004, null 값을 가지고 있는데, 여기서 문제가 생긴다!!!
DB에서 null값을 비교연산하게 되면, 예를 들어 DEPT_CD가 005일 때 001, 002, 003, 004까지 검사를 했다고 치자. 그렇다면 다음 연산할 것은 DEPT_CD(005) != NULL인데, 여기서 문제가 생긴다는 것이다. 005와 NULL을 비교했을 떄 UNKNOWN(=FALSE)값이 발생하게 되고 AND연산으로 처리하는 NOT IN구문에 대한 결과는 FALSE가 되어 출력되지 않는 다는 것!!!
그렇다면 NOT IN을 사용하기 위해선 NULL 값이 없는 테이블이어야 하나?
"그것은 아니다." 아래와 같이 설정해준다면 원하는 결과 값을 가질 수 있다.
-- 1
SELECT *
FROM EMPLOYEE A
WHERE A.DEPT_CD NOT IN (SELECT DEPT_CD
FROM DEPT
WHERE A.DEPT_CD IS NOT NULL);
-- 2
SELECT *
FROM DEPT A
WHERE A.DEPT_CD NOT IN (SELECT B.DEPT_CD
FROM EMPLOYEE B
WHERE B.DEPT_CD IS NOT NULL);
EXISTS/NOT EXISTS
SELECT *
FROM EMPLOYEE A
WHERE EXISTS (SELECT 'X'
FROM DEPT B
WHERE A.DEPT_CD = B.DEPT_CD);
SELECT *
FROM DEPT A
WHERE EXISTS (SELECT 'X'
FROM EMPLOYEE B
WHERE A.DEPT_CD = B.DEPT_CD);
드라이빙 테이블이 EMPLOYEE인 결과
드라이빙 테이블이 DEPT인 결과
서브쿼리에 조회되는 값만 나온 것을 알 수 있다.
SELECT *
FROM EMPLOYEE A
WHERE NOT EXISTS (SELECT 'X'
FROM DEPT B
WHERE A.DEPT_CD = B.DEPT_CD);
SELECT *
FROM DEPT A
WHERE NOT EXISTS (SELECT 'X'
FROM EMPLOYEE B
WHERE A.DEPT_CD = B.DEPT_CD);
드라이빙 테이블이 DEPT인 결과
서브쿼리에 조회되지않는 값만 나온 것을 알 수 있다.
JOIN/(+)
-- 1
SELECT A.*
FROM EMPLOYEE A
, DEPT B
WHERE A.DEPT_CD = B.DEPT_CD;
-- 2
SELECT A.*
FROM DEPT A
, EMPLOYEE B
WHERE A.DEPT_CD = B.DEPT_CD;
-- 2-1
SELECT DISTINCT A.*
FROM DEPT A
, EMPLOYEE B
WHERE A.DEPT_CD = B.DEPT_CD;
드라이빙 테이블이 EMPLOYEE인 결과
드라이빙 테이블이 DEPT인 결과
1)
EMPLOYEE 테이블에 DEPT_CD를 중복으로 가지는 직원이 있기 때문에 중복되는 값이 나올 수 있다.
중복된 값을 제거하면 원하는 값을 가질 수 있다. (아래와 같다)
2)
-- 1
SELECT A.*
FROM EMPLOYEE A
, DEPT B
WHERE A.DEPT_CD = B.DEPT_CD(+)
AND A.DEPT_CD IS NULL;
-- 2
SELECT A.*
FROM DEPT A
, EMPLOYEE B
WHERE A.DEPT_CD = B.DEPT_CD(+)
AND B.DEPT_CD IS NULL;
드라이빙 테이블이 EMPLOYEE인 결과
드라이빙 테이블이 DEPT인 결과
생각 정리
좋은 정보 감사합니다