SQL Cook: 3. 7장 두 테이블에 같은 데이터가 있는지 확인하기(종합)

0

SQL_COOK

목록 보기
18/35
post-thumbnail

해법

  • 뷰 'V'에는 존재하지 않고 인라인 뷰 'EMP'에만 존재하는 행을 찾는다
    • 차집합 연산을 떠올린다

    • 공통된 행들을 인라인 뷰 'EMP'에서 출력하지 않도록 WHERE절로 제한한다

      • 왜 굳이 GROUP BYCOUNT를 사용했을까?

      • WHERE절의 조건식을 보면 알 수 있다

      • 뷰 'V'는 인라인 테이블'EMP'에서 모든 행을 가져왔다
        따라서 단일 행끼리 WHERE절을 수행하면 무조건 값이 반환된다

      • 다른 점은 단 하나
        중복된 행이 존재한다는 점인데, 이를 찾아내기 위해서는 개수를 헤아려야 한다

  • 인라인 뷰 'EMP'에는 존재하지 않는 뷰 'V'의 행을 찾는다
    • 상동
  • 각자에게만 존재하는 행을 반환한다

어제는 인라인 뷰 '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을 가져오는 것에 의미는?
데이터가 존재하기는 하는데, 그 존재 여부만 확인하고, 그 내용을 가져오고 싶진 않을 때 사용하는 것 같다.

이제 순서를 다시 따져보겠다.

  1. 인라인 뷰'E'의 결과셋을 가져온다

  2. WHERE절의 조건을 적용한다
    조건이 만족되지 않는다면 행을 반환하지 않는다
    심지어 NULL도 반환하지 않을 것이다

  3. NULL마저 반환하지 않을 때, NOT EXISTS가 만족되고 해당 조건(WHERE절을 만족한 행)의 메인쿼리가 실행될 것이다

이렇게 서로의 차이점을 알 수가 있겠다.

앞쪽의 결과셋과 이번 결과셋을 UNION ALL로 포개줌으로써 최종 결과셋이 생성된다.


정리

매우 길었던 3. 7장이었다.
행 또는 열 또는 데이터 등 결과를 내는 해법을 중심으로 풀이를 정리해야겠다는 생각이 들었다.

상관 서브쿼리와 카디널리티의 개념은 아직 희미하다.

잘 메모해뒀다가 틈틈이 확인해야겠다.

0개의 댓글