차집합 연산을 떠올린다
공통된 행들을 인라인 뷰 'EMP'에서 출력하지 않도록 WHERE
절로 제한한다
왜 굳이 GROUP BY
와 COUNT
를 사용했을까?
WHERE
절의 조건식을 보면 알 수 있다
뷰 'V'는 인라인 테이블'EMP'에서 모든 행을 가져왔다
따라서 단일 행끼리 WHERE
절을 수행하면 무조건 값이 반환된다
다른 점은 단 하나
중복된 행이 존재한다는 점인데, 이를 찾아내기 위해서는 개수를 헤아려야 한다
어제는 인라인 뷰 'E'에만 존재하는 행을 반환하는 쿼리를 봤다.
오늘은 뷰 'V'에만 존재하는 행을 반환하는 쿼리를 볼 차례다.
쿼리의 구조는 완벽하게 동일하며, 뷰의 위치만 바뀌었을 뿐이다.
'뷰 V - E'꼴의 연산을 수행하는 것이다.
select *
from ( # VIEW V 에서도 모든 칼럼을 조회하여 그룹화했다
# cnt라는 열이 추가된 것 이외엔 동일하다
select v.empno, v.ename, v.job, v.mgr, v.hiredate,
v.sal, v.comm, v.deptno, count(*) as cnt
from v
group by empno, ename, job, mgr, hiredate,
sal, comm, deptno
) v
# 외부쿼리 영역: 서브쿼리의 반환값이 존재하지 않을 때 TRUE를 반환한다
# 단 한 건이라도 존재한다면 리턴값을 반환하고 더 이상 쿼리를 수행하지 않는다
where not exists (
# 서브쿼리로부터 가져오는 칼럼이 NULL이어야 한다?
select null
from (
# 인라인 뷰'E'의 모든 칼럼을 조회하여 그룹화했다
# cnt라는 열이 추가된 것 이외엔 동일하다
select e.empno, e.ename, e.job, e.mgr, e.hiredate,
e.sal, e.comm, e.deptno, count(*) as cnt
from emp e
group by empno, ename, job, mgr, hiredate,
sal, comm, deptno
) e
# 모든 값이 일치하는 행으로 조건을 제한한다
# 이를 만족하지 않는다면 NULL을 반환할 것이다
where v.empno = e.empno
and v.ename = e.ename
and v.job = e.job
and coalesce(v.mgr, 0) = coalesce(e.mgr, 0)
and v.hiredate = e.hiredate
and v.sal = e.sal
and v.deptno = e.deptno
and v.cnt = e.cnt
and coalesce(v.comm, 0) = coalesce(e.comm, 0)
)
SELECT NULL
이 절이 대관절 무엇을 의미하는가?
이게 정말 궁금했는데 깜빡했다!
쿼리를 한 번 입력해봤다.
select null from emp;
>>
+------+
| NULL |
+------+
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
| NULL |
+------+
15 rows in set (0.001 sec)
NULL
은 해당 이름의 칼럼이 존재하지 않아도 그냥 조회가 된다.
테이블이 가진 행의 개수만큼 출력되는 것을 볼 수 있다.
그렇다면 SELECT NULL
을 가져오는 것에 의미는?
데이터가 존재하기는 하는데, 그 존재 여부만 확인하고, 그 내용을 가져오고 싶진 않을 때 사용하는 것 같다.
이제 순서를 다시 따져보겠다.
인라인 뷰'E'의 결과셋을 가져온다
WHERE
절의 조건을 적용한다
조건이 만족되지 않는다면 행을 반환하지 않는다
심지어 NULL
도 반환하지 않을 것이다
NULL
마저 반환하지 않을 때, NOT EXISTS
가 만족되고 해당 조건(WHERE
절을 만족한 행)의 메인쿼리가 실행될 것이다
이렇게 서로의 차이점을 알 수가 있겠다.
앞쪽의 결과셋과 이번 결과셋을 UNION ALL
로 포개줌으로써 최종 결과셋이 생성된다.
매우 길었던 3. 7장이었다.
행 또는 열 또는 데이터 등 결과를 내는 해법을 중심으로 풀이를 정리해야겠다는 생각이 들었다.
상관 서브쿼리와 카디널리티의 개념은 아직 희미하다.
잘 메모해뒀다가 틈틈이 확인해야겠다.