Programming/Microsoft SQL Server
하위Query는 Query문 안에 또다른 Select Query문이 존재하는 것을 말합니다.(이런 Query는 다른말로 내부Query 라고도 하며 반면 하위Query를 포함하고 있는 Query를 외부Query라고 합니다.)

이런한 구조의 Query는 하위에서 Query가 수행될때마다 하나의 값만을 반환해야 합니다.

1. 하나의 열처럼 조회

Select B.BusinessEntityID, (Select Name From HumanResources.Department As A Where A.DepartmentID = B.DepartmentID)
From HumanResources.EmployeeDepartmentHistory As B

HumanResources.EmployeeDepartmentHistory Table을 조회할때 DepartmentID에 따른 Name값은 하위 Query를 통해 조회합니다.


만일 DepartmentID값에 따라 같은 Name이 존재한다면 처리가 곤란해 지게 되고 당연히 오류를 발생시키게 됩니다. 따라서 하위Query에서는 하나의 값만 발생시켜야 된다는 점을 유념하시기 바랍니다.
또한 하위Query 사용시에는 반드시 괄호를 통해 하위Query를 구분해 줘야 합니다.

(Select Name From HumanResources.Department As A Where A.DepartmentID = B.DepartmentID)

2. 조건지정

Select FirstName, MiddleName, LastName
From Person.Person
Where BusinessEntityID = (Select BusinessEntityID From Person.PersonPhone Where PhoneNumber = '815-555-0138')

Person.Person Table의 FirstName, MiddleName, LastName을 조회하되 BusinessEntityID가 Person.PersonPhone Table에서 PhoneNumber가 '815-555-0138'에 해당하는 Name만 조회합니다.


만일 조건처럼 사용된 하위Query에서 여러개의 값을 반환하는 경우에는 = 대신 In을 사용하여 지정하도록 합니다.

Select FirstName, MiddleName, LastName
From Person.Person
Where BusinessEntityID In (Select BusinessEntityID From Person.PersonPhone Where PhoneNumberTypeID = 3)

하위Query에서 반환하는 모든 값이 BusinessEntityID와 일치하는 FirstName, MiddleName, LastName만 조회합니다.


3. 하위Query를 Table처럼 사용하기

하위Query전체를 열이나 조건식이 아닌 하나의 Table처럼 사용하여 조회할 수도 있으며 이때 외부Query에서는 하위Query에서 조회된 결과를 다시 재 가공하여 출력시킬 수도 있습니다.

Select Count(Color), Sum(A.Price)
From (Select Color, Sum(ListPrice) As Price From Production.Product Group By Color) As A

하위Query에서는 Production.Product Table의 Color에 따라 ListPrice값의 합계를 구하고 외부Query에서는 하위Query에서 구해진 ListPrice의 전체합과 Color별 행수를 구하도록 합니다.


그런데 하위Query만 따로 실행해 보면

Select Color, Sum(ListPrice) As Price From Production.Product Group By Color


전체 ListPrice의 합계는 외부Query에서 구해진게 맞지만 Color에 대한 행수는 10행에 불과합니다. 이는 외부Query에서 Color의 Count를 구할때 Null값은 제외하였기 때문입니다.

4. 상관하위Query

위에서 언급한 하위Query는 Query동작의 순서상 하위Query가 먼저 실행된 후 그 실행을 토대로 외부Query가 동작하는 방식이었으며 또한 외부Query와 하위Query가 같이 존재한다 하더라도 하위Query만 독립적으로 동작하는 것이 가능했습니다.

하지만 상관하위Query는 일반 하위Query처럼 독립적으로 실행하는 것도 불가능하고 동작순서도 외부Query가 먼저 실행된 후 내부Query가 동작하는 특징을 갖고 있습니다.

Select ProductID, Name, ProductNumber
From Production.Product As A
Where 40 < (Select Max(ListPrice) From Production.ProductListPriceHistory As B Where A.ProductID = B.ProductID)

Production.Product Table에서 ProductID, Name, ProductNumber열을 조회하되 Production.ProductListPriceHistory의 ProductID열 ListPrice값이 최대 40이상인 것만 조회하도록 합니다.


보시는 것 처럼 하위Query와 외부Query가 서로 조건식을 통하여 연관되어 있기 때문에 내부Query만 따로 실행시킬 수는 없습니다.

동작순서 또한 외부Query에서 Production.Product Table의 ProductID, Name, ProductNumber 열값을 불러오고 이중에서 기준이 되는 ProductID값을 내부Query에게 던져 주게 됩니다. 그럼 내부 Query에서는 넘겨받은 ProductID값으로 ListPrice의 최대값을 조회하여 그 결과 값을 다시 외부Query에 넘기게 됩니다. 이때  외부 Query는 내부 Query로 부터 넘겨받은 값이 40이상인지를 판단하여 처리를 진행합니다.

이러한 특징 때문에 외부Query가 먼저 실행되어야 내부Query가 작동할 수 있는 것입니다.

참고:
상관하위 Query가 동작하는 단위는 Table전체 단위가 아닌 행단위로 이루어 지게 됩니다. 그렇기 때문에 외부Query에서 조회하는 행이 크면 클수록 내부 Query에서 조회할때 조건을 비교하므로 시간이 오래 걸릴 수 있습니다.

하위Query에서 보시면 ListPrice값을 조회할때 Max함수를 써서 최대값만을 가져오도록 했습니다. 이는 Production.ProductListPriceHistory Table에 하나의 ProductID별로 여러건의 데이터가 존재하기 때문입니다. 즉, 값을 2개이상 반환하면 오류를 일으키게 되므로 주의하시기 바랍니다.

'Programming > Microsoft SQL Server' 카테고리의 다른 글

[SQL] 시간관련 형식 변환  (0) 2010.04.30
[SQL] Table 조회시 합계 표시하기  (0) 2010.04.26
[SQL] 하위 Query(Sub Query)  (0) 2010.04.21
[SQL] 흐름제어 구문  (0) 2010.04.08
[SQL] 데이터(Data) 형식  (2) 2010.04.01
[SQL] Table Join  (3) 2010.03.31
0 0