SSISO Community

시소당

33. Nested Query(중첩질의) 오라클/자바[ERP]

§ Nested Query

 

 

1. 중첩질의(nested query)의 개요

 

중첩질의(nested query or embeded query)는 다음과 같이 query 속에 또 다른 query가 있는 구조이다.


 

 


 

 

 

 

<예제-1>의 내용를 다시 한번 보도록 하자.

 


 

<employee>테이블에서 갑을병의 직책이 과장이므로 <예제-1>의 query는

 

              “직책이 과장인 사원들의 이름과 직책을 모두 검색하라”

 

라고 하면 될 것 같은데, 왜 이리 복잡하게 중첩질의를 만들어서 표현하는 것일까. 이것은 우리가 query를 작성할 때에 ‘갑을병’의 직책을 아직 모를 수도 있고, 또는 ‘갑을병’의 직책이 지금 과장인 것은 알고 있지만, 직책의 변화가 예상되고 직책이 변화되었을 때에도 역시 이 query가 유효하려면 <예제-1>과 같이 작성하는 것이 보다 적절하기 때문이다. 보다 근본적으로 말하자면 우리가 query 를 작성할 때, 다른 query의 결과로 나온 값이나 애트리뷰트, 테이블 등을 참조해야 하는 경우가 있다. 이러한 경우 query 속에 query가 있는 중첩질의가 나타나게 되는 것이다. 외부질의에 포함되는 내부질의는 그 자체로 다시 내부질의를 가질 수도 있다..  중첩질의는 <예제-1>의 형태뿐만 아니라, 다른 형태도 추가적으로 가지고 있으며, 매우 다양한 query에 쓰여진다. 

 

 

2. 내부질의(subquery)의 형태

 

내부질의(subquery)는 다음과 같이 세 가지의 형태로 쓰인다.

 


 

 

2-1. scalar형

 

내부질의(subquery)의 scalar형은 질의의 결과로 단일값을 반환한다. 단일값이 쓰이는 곳이면 어디든지 쓰일 수 있으며, 대부분 SELECT절과 WHERE절에 쓰인다.

 

2-1-1. SELECT절에 쓰인 경우

 


<방법-1>

<예제-1>에서 검색해야 할 사원이름과 직급은 <employee>테이블에, 부서명은 <department>테이블에 있으므로 두 테이블을 조인하여 검색한다.

 


<방법-2>

<QUERY-1>은 내부질의(subquery)의 scalar형을 사용하여 다음과 같이 작성할 수 있다.
 


< QUERY-1>과 <QUERY-2>의 형식은 서로 다르나 결과는 같게 나온다. 어느 QUERY를 선택하느냐는 쿼리최적화에 대한 쿼리수행자의 선택에 달려 있다. 참고로, 다음 그림은 MS의 쿼리분석기로 본 두 쿼리의 실행계획에 대한 내용이다.

 

 


2-1-2. WHERE절에 쓰인 경우

 

scalar형이 WHERE절에 쓰인 경우는 <1. 중첩질의(nested query)의 개요>의 <예제-1>을 참고하기 바란다.

 

 

2-2. predicate형

 

predicate형은 주로 WHERE절과 HAVING절에 쓰이며, IN, ANY, SOME, ALL, EXISTS 등의 키워드가 사용된다.

 

2-2-1. IN

 

IN의 일반적인 형태는 다음과 같다.

 

 


<방법-1>

▶ step1

사원들의 이름을 검색하므로 SELECT emp_name

 

▶ step2

emp_name는 <employee>테이블에 있으므로 → FROM employee

 

▶ step3

<employee>테이블에는 부서번호(dept_no)가 있고 영업부는 1번, 개발부는 3번이다.

따라서 다음과 같은 QUERY를 작성할 수 있다.



여기서는 <QUERY-1>을 사용한다.

 

▶ step4

(1, 3)은 부서(department)테이블에서 부서번호(dept_no)를 구하는 것이므로 다음 QUERY의 결과로 얻어진다.

 

 

▶ step5

최종적으로 완성된 QUERY는 다음과 같다

 


다음의 <QUERY-4>은 <QUERY-3>와 같은 결과값을 반환한다.

 

 

☞ 참고


위 그림은 <QUERY-1>, <QUERY-3>, <QUERY-4>에 대한 MS-SQL의 쿼리분석기의 실행계획이다. <QUERY-3>은 Left Semi Join, <QUERY-4>는 Inner Join이 쓰였으며, 쿼리비용은 동등하게 평가되고 있다. 결과가 같게 나오는 서로 다른 QUERY가 있다는 것은 QUERY수행자에게 선택을 요구한다. 어떤 QUERY를 선택할 것인가. to choose or not to choose, that’s a question.

 

☞ Advice

‘속하는’ 것을 구하기 위해 IN을 사용하듯이 ‘속하지 않는’ 것을 구하기 위해 NOT IN을 사용할 수 있다. <QUERY-1>과 같이 INNOT IN을 사용한 열거형 QUERY도 가능하다. 즉, <예제-2>에 대한 <QUERY-5>와 <QUERY-6>의 결과는 같다.
 


 

2-2-2. SOME(ANY) & ALL

 

SOME(ANY)은 ‘어떤(적어도 하나의, at least one row)’ 값에 대한 비교이다. SOME(ANY)의 일반적인 형태는 다음과 같다.

 




SOME(ANY)로부터 추측할 수 있듯이, ALL은 ‘모든(all row)’ 값에 대한 비교이다. ALL의 일반적인 형태는 다음과 같다.
 

 


<QUERY-1>은 물론 다른 형태의 QUERY로도 작성할 수가 있다. 여기서는 SOME의 사용 예로써 위와 같이 작성한 것이다. = SOME은 IN과 동일하다.

 


<> ALLNOT IN과 같다.
 


 
2-2-3. EXISTS
 

IN 은 내부질의(subquery)의 결과값 내에 일치하는 것이 있어야 참이 되는 것에 반해, EXISTS는 내부질의(subquery)의 결과값이 어떤 것이든 내부질의가 결과값만 반환하면(행만 존재하면, at least one row) 참이 된다.

 

EXISTS의 기본구문은 다음과 같다.

 

EXISTS는 비교구문이 아니기 때문에 IN, SOME(ANY), ALL과 달리 EXISTS 앞에 subquery-1의 결과값과 비교하는 값인 value-1이 없다는 것에 주목하라.



<department>테이블에는 1번(영업)부터 2번(기획), 3번(개발), 4번(총무)까지 총 4개의 부서가 존재한다. 그러나 <employee>테이블에는 4번(총무) 부서가 나타나지 않는다.

 

▶ step1

부서번호와 이름을 검색하므로 SELECT dept_no, dept_name

 

▶ step2

dept_no와 dept_name이 <department>테이블에 있으므로

FROM department

 

▶ step3

dept_no 와 dept_name을 하나씩 추출할 때, 예를 들면 (1, 영업)을 추출할 때, (1, 영업)에 해당되는(소속되는) 사원이 존재하는 가를 판단해야 한다. 그러나 <department>테이블에는 사원의 정보가 없으며, 따라서 당연히 사원테이블인 <employee>테이블을 참조하여야 한다. 우선 <employee>테이블에서 사원정보를 추출한다.

 

SELECT * (← 편의상 *을 사용한 것이지만 emp_no 등 다른 것도 관계없다)

FROM employee

 

▶ step4

이제 <department>테이블과 <employee>테이블을 연결해 보자. 두 테이블은 dept_no가 <employee>테이블의 외래키로 연결되고 있다.
 


(1, 영업)은 <employee>테이블에 ‘김개동’, ‘아무개’ 등의 해당 사원이 있으므로 내부질의의 결과값이 존재하며, 따라서 (1, 영업)은 정상적으로 추출된다. (2, 기획), (3, 개발) 등도 마찬가지의 근거에 의해서 정상적으로 추출된다. 그러나 (4, 총무)는 “e.dept_no = d.dept_no ”를 만족하는 e.dept_no가 없으며 내부질의의 결과값이 존재하지 않게 되며, 따라서 4번 부서에 대한 정보는 추출되지 않는다.

 

 

<QUERY-1>은 IN과 조인을 사용하여 각각 다음의 <QUERY-2>, <QUERY-3>과 같이 바꿀 수도 있다.



< QUERY-2>나 <QUERY-3>가 <QUERY-1>보다 구문에 대한 직관적 이해도가 높다. 물론 이것은 개인의 SQL구문에 대한 이해의 깊이와 취향에 따라 다를 수도 있지만 말이다. 여러분은 어떤 구문을 작성할 것이며, 어떤 구문을 선택할 것인가.

 

노력한만큼 알게되고

아는만큼 보이게 되며

보이는만큼 작성하게 된다? ^^

 

 


 

1314 view

4.0 stars