이것은 하위 쿼리에 대한 일련의 기사 중 두 번째입니다. 이 기사에서는 SELECT 문의 열 목록에있는 하위 쿼리에 대해 설명합니다. 다른 문서에서는 다른 절에서의 사용에 대해 설명합니다.
이 강의의 모든 예제는 Microsoft SQL Server Management Studio 및 AdventureWorks2012 데이터베이스를 기반으로합니다. 내 가이드 SQL Server 사용 시작하기를 사용하여 이러한 무료 도구를 사용할 수 있습니다.
Select 문에서 하위 쿼리 사용
하위 쿼리가 열 목록 내에 배치 될 때 사용됩니다. 단일 값을 반환합니다. 이 경우 하위 쿼리를 단일 값 식으로 생각할 수 있습니다. 반환 된 결과는 “2 + 2″식과 다르지 않습니다. 물론 하위 쿼리도 텍스트를 반환 할 수 있지만 요점은 알 수 있습니다!
하위 쿼리로 작업 할 때 주 문을 외부 쿼리라고도합니다. 하위 쿼리는 괄호로 묶여 있기 때문에 쉽게 찾을 수 있습니다. .
하위 쿼리를 사용할 때는주의하세요. 사용하기는 재미있을 수 있지만 쿼리에 추가할수록 쿼리 속도가 느려질 수 있습니다.
평균을 계산하는 간단한 하위 쿼리
SalesOrderDetail을 표시하고 전체 평균 SalesOrderDetail LineTotal과 비교하는 간단한 쿼리로 시작해 보겠습니다. 사용할 SELECT 문은 다음과 같습니다.
SELECT SalesOrderID,LineTotal,(SELECT AVG(LineTotal) FROM Sales.SalesOrderDetail) AS AverageLineTotalFROM Sales.SalesOrderDetail;
이 쿼리는 다음과 같은 결과를 반환합니다.
위에 빨간색으로 표시된 하위 쿼리가 먼저 실행됩니다. 평균 LineTotal을 구합니다.
SELECT AVG(LineTotal)FROM Sales.SalesOrderDetail
이 결과는 열 목록에 다시 연결되고 쿼리가 계속됩니다. 몇 가지 지적하고 싶은 사항이 있습니다. :
- 하위 쿼리는 괄호로 묶여 있습니다. .
- SELECT 문에서 하위 쿼리를 사용하면 하나의 값만 반환 할 수 있습니다. 열을 선택하면 행에 대해 하나의 값이 반환되며 동일한 패턴을 따라야합니다.
- 일반적으로 하위 쿼리는 전체 쿼리에 대해 한 번만 실행되며 그 결과는 재사용됩니다. . 이는 반환 된 각 행에 대해 쿼리 결과가 다르지 않기 때문입니다.
- 가독성을 높이려면 열 이름에 별칭을 사용하는 것이 중요합니다.
표현식의 단순 하위 쿼리
예상 할 수 있듯이 하위 쿼리의 결과는 다른 표현식에서 사용할 수 있습니다. 이전 예를 기반으로 하위 쿼리를 사용하여 LineTotal이 평균과 얼마나 다른지 확인하겠습니다.
분산은 단순히 LineTotal에서 평균 라인 합계를 뺀 값입니다. 다음 하위 쿼리에서는 파란색으로 표시했습니다. 다음은 분산에 대한 공식입니다.
LineTotal - (SELECT AVG(LineTotal) FROM Sales.SalesOrderDetail)
괄호로 묶인 SELECT 문이 하위 쿼리입니다. 앞의 예와 마찬가지로이 쿼리는 한 번 실행되고 숫자 값을 반환 한 다음 각 LineTotal 값에서 뺍니다.
다음은 최종 형식의 쿼리입니다.
SELECT SalesOrderID, LineTotal, (SELECT AVG(LineTotal) FROM Sales.SalesOrderDetail) AS AverageLineTotal, LineTotal - (SELECT AVG(LineTotal) FROM Sales.SalesOrderDetail) AS VarianceFROM Sales.SalesOrderDetail
결과는 다음과 같습니다.
select 문에서 하위 쿼리로 작업 할 때 일반적으로 작성합니다. 먼저 하위 쿼리를 테스트하십시오. SELECT 문은 매우 빠르게 복잡해질 수 있습니다. 조금씩 쌓아가는 것이 가장 좋습니다. 다양한 부분을 개별적으로 빌드하고 테스트하면 디버깅에 정말 도움이됩니다.
상관 된 쿼리
외부 쿼리의 값을 하위 쿼리의 절에 통합하는 방법이 있습니다. 이러한 유형의 쿼리는 하위 쿼리의 결과가 어떤 형식으로 외부 쿼리의 값에 연결되기 때문에 상관 된 하위 쿼리라고합니다. 상관 된 쿼리를 동기화 된 쿼리라고도합니다.
상관이 무엇을 의미하는지 이해하는 데 문제가있는 경우 Google에서 다음 정의를 확인하세요.
Correlate : “상호 관계 또는 연결이 있습니다. 어떤 것이 다른 것에 영향을 미치거나 의존합니다.”
상관 된 하위 쿼리의 일반적인 사용은 내부 쿼리의 WHERE 절에있는 외부 쿼리의 열 중 하나에 사용됩니다. 이것은 많은 경우에 상식적으로 사용됩니다. 내부 쿼리를 데이터 하위 집합으로 제한합니다.
상관 하위 쿼리 예
각 SalesOrderDetail LineTotal 및 전체 매출에 대한 평균 LineTotal을 다시보고하여 상관 하위 쿼리 예를 제공합니다. 주문.
이 요청은 우리가 계산하는 평균이 각 판매 주문에 따라 다르기 때문에 이전 예와 크게 다릅니다.
상관 된 하위 쿼리가 작동하는 곳입니다. 외부 쿼리의 값을 가져 와서 하위 쿼리의 필터 기준에 통합합니다.
평균 라인 합계를 계산하는 방법을보십시오. 이를 위해 하위 쿼리가있는 SELECT 문을 보여주는 그림을 작성했습니다.
도표. SELECT 문은 외부 쿼리와 하위 쿼리의 두 부분으로 구성됩니다. 외부 쿼리는 모든 SalesOrderDetail 줄을 검색하는 데 사용됩니다.하위 쿼리는 특정 SalesOrderID에 대한 판매 주문 세부 정보 라인을 찾고 요약하는 데 사용됩니다.
단계를 구두로 처리하려는 경우 다음과 같이 요약하겠습니다.
- SalesOrderID를 가져옵니다.
- SalesOrderID가 일치하는 모든 SalesOrderDetail 항목에서 평균 LineTotal을 반환합니다.
- 외부 쿼리에서 다음 SalesOrderID로 계속 이동하고 1 단계와 2 단계를 반복합니다.
AdventureWork2012 데이터베이스에서 실행할 수있는 쿼리는 다음과 같습니다.
SELECT SalesOrderID, SalesOrderDetailID, LineTotal, (SELECT AVG(LineTotal) FROM Sales.SalesOrderDetail WHERE SalesOrderID = SOD.SalesOrderID) AS AverageLineTotalFROM Sales.SalesOrderDetail SOD
검색 결과는 다음과 같습니다.
- 쿼리 결과를 더 쉽게 읽을 수 있도록 열 별칭을 사용했음을 알 수 있습니다.
- 또한 테이블 별칭 인 SOD를 사용했습니다. 외부 쿼리. 이렇게하면 하위 쿼리에서 외부 쿼리의 값을 사용할 수 있습니다. 그렇지 않으면 쿼리가 상관되지 않습니다!
- 테이블 별칭을 사용하면 각 테이블의 열이 모호하지 않게됩니다.
상관 하위 쿼리 분석
이제 SQL을 사용하여이 문제를 분석해 보겠습니다.
시작하려면 SalesOrderDetailID 20에 대한 예제 만 가져 오겠다고 가정하겠습니다. 해당 SalesOrderID는 43661입니다.
이 항목의 평균 LineTotal을 구하는 것은 쉽습니다.
SELECT AVG(LineTotal)FROM Sales.SalesOrderDetailWHERE SalesOrderID = 43661
이 값은 2181.765240을 반환합니다.
이제 평균값을 얻을 수 있습니다. 쿼리에 연결
SELECT SalesOrderID, SalesOrderDetailID, LineTotal, 2181.765240 AS AverageLineTotalFROM Sales.SalesOrderDetailWHERE SalesOrderDetailID = 20
하위 쿼리를 사용하면
SELECT SalesOrderID, SalesOrderDetailID, LineTotal, (SELECT AVG(LineTotal) FROM Sales.SalesOrderDetail WHERE SalesOrderID = 43661) AS AverageLineTotalFROM Sales.SalesOrderDetailWHERE SalesOrderDetailID = 20
최종 쿼리는 :
SELECT SalesOrderID, SalesOrderDetailID, LineTotal, (SELECT AVG(LineTotal) FROM Sales.SalesOrderDetailWHERE SalesOrderID = SOD.SalesOrderID) AS AverageLineTotalFROM Sales.SalesOrderDetail AS SOD
다른 테이블이있는 상관 하위 쿼리
상호 관련된 하위 쿼리 또는 모든 하위 쿼리는 다음과 다른 테이블을 사용할 수 있습니다. 외부 쿼리. 이것은 SalesOrderHeader와 같은 “상위”테이블로 작업 할 때 유용 할 수 있으며 결과에 SalesOrderDetail의 항목과 같은 하위 행의 요약을 포함하려고 할 때 유용 할 수 있습니다.
OrderDate, TotalDue 및 판매 주문 세부 정보 라인 수.이를 위해 다음 다이어그램을 사용하여 베어링을 얻을 수 있습니다.
이 작업을 수행하기 위해 SELECT 문에 상관 하위 쿼리를 포함하여 COUNT 개의 SalesOrderDetail 행을 반환합니다. 외부 쿼리의 SalesOrderID를 필터링하여 올바른 SalesOrderDetail 항목을 계산하는지 확인합니다.
최종 SELECT 문은 다음과 같습니다.
SELECT SalesOrderID, OrderDate, TotalDue, (SELECT COUNT(SalesOrderDetailID) FROM Sales.SalesOrderDetail WHERE SalesOrderID = SO.SalesOrderID) as LineCountFROM Sales.SalesOrderHeader SO
결과는 다음과 같습니다.
이 예에서 주목해야 할 사항은 다음과 같습니다.
- 서브 쿼리가 외부 쿼리와 다른 테이블에서 데이터를 선택합니다.
- SQL 및 결과를 더 쉽게 읽을 수 있도록 열 별칭을 사용합니다.
- k 당신의 where 절! 하위 쿼리 WHERE 절에 테이블 이름 또는 별칭을 포함하는 것을 잊은 경우 쿼리는 상관되지 않습니다.
상호 관련된 하위 쿼리와 내부 조인
중요합니다. 하위 쿼리 또는 조인을 사용하여 동일한 결과를 얻을 수 있음을 이해합니다. 둘 다 동일한 결과를 반환하지만 각 방법에는 장점과 단점이 있습니다.
SalesHeader 항목에 대한 광고 항목을 계산하는 마지막 예를 고려하세요.
SELECT SalesOrderID, OrderDate, TotalDue, (SELECT COUNT(SalesOrderDetailID) FROM Sales.SalesOrderDetailWHERE SalesOrderID = SO.SalesOrderID) as LineCountFROM Sales.SalesOrderHeader SO
이 같은 쿼리는 GROUP BY와 함께 INNER JOIN을 사용하여 수행 할 수 있습니다.
SELECT SO.SalesOrderID, OrderDate, TotalDue, COUNT(SOD.SalesOrderDetailID) as LineCountFROM Sales.SalesOrderHeader SO INNER JOIN Sales.SalesOrderDetail SOD ON SOD.SalesOrderID = SO.SalesOrderIDGROUP BY SO.SalesOrderID, OrderDate, TotalDue
어떤 것이 더 빠릅니까?
많은 사람들이 하위 쿼리가 더 느리기 때문에 피하라고 말할 것입니다. 그들은 상관 된 하위 쿼리가 외부 쿼리에서 반환 된 각 행에 대해 한 번씩 “실행”해야하는 반면 INNER JOIN은 데이터를 한 번만 통과하면된다고 주장합니다.
내 자신 이요? 위의 두 가지 예에 대한 내 조언을 따랐고 계획이 동일하다는 것을 알았습니다!
데이터가 더 있으면 계획이 변경된다는 말은 아니지만 제 요점은 대부분의 SQL DBMS 최적화 프로그램은 쿼리를 실행하는 가장 좋은 방법을 알아내는 데 정말 능숙합니다. 그들은 하위 쿼리 또는 INNER JOIN과 같은 구문을 사용하여 실제 실행 계획입니다.
어떤 것이 더 읽기 쉬운가요?
당신이 편한 것에 따라 INNER JOIN 예제가 상관 된 쿼리보다 읽기 쉬울 수 있습니다. 개인적으로, 이 예에서는 상관 하위 쿼리가 더 직접적으로 보이기 때문에 좋아합니다. 무엇이 계산되고 있는지보기가 더 쉽습니다.
내 생각에는 INNER JOIN이 덜 직접적입니다. 먼저 모든 판매 세부 정보 행이 반환되고 요약되는 것을 확인해야합니다. 성명서 전체를 읽어보기 전까지는이 사실을 알 수 없습니다.
어떤 것이 더 낫습니까?
당신의 생각을 알려주세요. 상관 하위 쿼리 또는 INNER JOIN 예제를 사용하고 싶은지 듣고 싶습니다.