공통 테이블 식(CTE) 은 단순 쿼리로부터 파생된 임시 결과 집합입니다. CTE 는 파생된 테이블을 사용하는 것처럼, 동일한 수단으로 사용 되어질 수 있습니다. CTE는 또한 자신에 대한 참조를 포함할 수 있습니다. 이는 데이터베이스 개발자가 재귀 쿼리를 작성할 수 있도록 해줍니다. CTE 는 또한 뷰 대신 사용 되어질 수도 있습니다. 개념적으로는 임시테이블과 비슷합니다.더 적은 코드로 임시테이블, 재귀호출등을 처리할 수 있습니다.
기존 SQL 2000 에서 사용 하던 방식
select SalesPersonID, count(*) as NumSales into #tmp from Sales.SalesOrderHeader Group by SalesPersonID select ts.SalesPersonID, sp.SalesYTD, ts.NumSales from Sales.SalesPerson sp inner join #tmp ts on ts.SalesPersonID = sp.SalesPersonID order by NumSales Desc
SQL 2005의 CTE 를 이용한 방식
with TopSales (SalesPersonID, NumSales) as ( Select SalesPersonID, Count(*) From Sales.SalesOrderHeader Group BY SalesPersonID) select ts.SalesPersonID, sp.SalesYTD, ts.NumSales from Sales.SalesPerson sp inner join TopSales ts on ts.SalesPersonID = sp.SalesPersonID order by NumSales Desc
1. 파생된 테이블로 사용된 CTE 필터링 하기
뷰로 리턴된 결과집합을 필터링하는 것과 마찬가지로, 여러분은 공통 테이블 식(CTE) 안에 포함된 결과 집합을 필터링 할 수 있습니다.
WITH SalesCTE(ProductID , SalesOrderID) AS ( SELECT ProductID , COUNT(SalesOrderID) FROM Sales.SalesOrderDetail GROUP BY ProductID ) SELECT * FROM SalesCTE WHERE SalesOrderID > 50 --50회이상주문된모든제품들
2. CTE 로 집계하기
공통 테이블 식(CTE) 으로 리턴된 데이터를 가지고 집계 또는 그 밖의 다른 계산을 수행하는 것은 기본 테이블로부터 리턴된 데이터를 가지고 집계 및 기타 계산을 수행하는 것과 유사합니다.
WITH SalesCTE(ProductID , SalesOrderID) AS ( SELECT ProductID , COUNT(SalesOrderID) FROM Sales.SalesOrderDetail GROUP BY ProductID ) SELECT AVG(SalesOrderID) FROM SalesCTE WHERE SalesOrderID > 50 -- 50 회이상주문된모든제품들의평균주문횟수
3. 공통 테이블 식(CTE)을 사용하는 재귀 쿼리
공통 테이블 식(CTE)의 진정한 위력은 재귀 쿼리를 작성하는 데에 있습니다. 공통 테이블 식(CTE) 이 자기 자신에 대한 참조가 가능하기 때문에, 재귀 쿼리의 작성을 비교적 간단히, 수월하게 할 수 있습니다.
CREATE TABLE CarParts ( CarID int NOT NULL , Part varchar(15) , SubPart varchar(15) , Qty int ) GO INSERT CarParts VALUES(1 , 'Body' , 'Door' , 4) INSERT CarParts VALUES(1 , 'Body' , 'Trunk Lid' , 1) INSERT CarParts VALUES(1 , 'Body' , 'Car Hood' , 1) INSERT CarParts VALUES(1 , 'Door' , 'Handle' , 1) INSERT CarParts VALUES(1 , 'Door' , 'Lock' , 1) INSERT CarParts VALUES(1 , 'Door' , 'Window' , 1) INSERT CarParts VALUES(1 , 'Body' , 'Rivets' , 1000) INSERT CarParts VALUES(1 , 'Door' , 'Rivets' , 100) INSERT CarParts VALUES(1 , 'Door' , 'Mirror' , 1)
자동차의 부품 및 하위 부품에 대한 정보를 가지고 있는 테이블을 만들기 위한 쿼리 입니다. 보통 이러한 정보를 담고 있는 테이블을 재료표(bill of materials)라고 부릅니다. 재귀적 CTE 는 재료표 , 조직도 및 기타 계층적인 구조를 갖는 데이터를 반환하는 작업을 쉽게 할 수 있도록 합니다.
지금 생성하는 테이블 정보에서 Body 와 같은 부품이 여러 하위 부품들을 가지고 있다는 사실을 주목하십시오.. 예를 들어, Body 부품은 1000 개의 못(rivet) 을 하위 부품으로 가지고 있고, Body 의 하위 부품인 Door 또한 자신(Door) 의 하위 부품으로 100개의 못(rivet)을 가지고 있습니다.
WITH CarPartsCTE(SubPart , Qty) AS ( -- 앵커멤버(Anchor Member): -- CarPartsCTE 자신을참조하지않는SELECT 쿼리 SELECT SubPart , Qty FROM CarParts WHERE Part = 'Body' UNION ALL -- 재귀멤버(Recursive Member): -- CTE(CarPartsCTE) 자기자신을참조하는SELECT 쿼리 SELECT CarParts.SubPart , CarPartsCTE.Qty * CarParts.Qty FROM CarPartsCTE INNER JOIN CarParts ON CarPartsCTE.SubPart = CarParts.Part WHERE CarParts.CarID = 1 ) -- 출력쿼리 SELECT SubPart , SUM(Qty) as q FROM CarPartsCTE GROUP BY SubPart
재귀적 CTE 는 최소한 2개 이상의 쿼리들로 구성 되어집니다. 첫번째 요소로 구성된 쿼리는 CTE 자체를 참조하지 않는 쿼리입니다. 이러한 쿼리 정의는 CTE 구조의 기본 결과 집합을 형성하기 때문에 앵커 멤버(anchor member)라고 합니다. 두 번째 구성요소는 재귀 멤버(recursive member) 라고 불리워지는 재귀 쿼리입니다. 이러한 쿼리들은 UNION ALL 연산자에 의해 구별되어 집니다.
자동차의 본체(Body) 를 만들기 위해 필요한 부품들의 총 수량에 대한 리스트를 얻어오는 쿼리 입니다. 공통 테이블 식(CTE)은 맨 처음 간단한 쿼리(“SELECT SubPart, Qty FROM CarParts WHERE Part = 'Body'”.)로부터 기본 결과 집합을 만듭니다. 그 다음, 이 부품들의 하위 부품들과 이 하위 부품의 개수(필요한 상위 부품의 개수 * 상위 부품 단위당 필요한 하위 부품 개수) 에 대한 정보를 얻어오는 쿼리문을 UNION ALL 연산자로 결합합니다. 두 번째 쿼리문의 INNER JOIN 문장 안에 CarPartsCTE 라는 이름을 가진 공통 테이블 식(CTE) 자체에 대한 참조 (재귀 참조) 를 포함하는 것입니다.
재귀 쿼리를 이용한 1~ 10까지 쿼리
WITH TEST AS( SELECT IDX = 1 UNION ALL SELECT IDX = IDX + 1 FROM TEST WHERE IDX < 10 )SELECT * FROM TEST
'MSSQL > SQL Server 2005 new Feature' 카테고리의 다른 글
OUTPUT 절 (insert,update,delete) (1) | 2009.10.30 |
---|---|
RANK()함수를 활용하자! - 향샹된 순위함수(분석함수) 알아보기 (2) | 2009.10.29 |
MS SQL 2005 new Feature - 8KB를 초과하는 행 오버플로 데이터 (3) | 2009.10.28 |
Try Catch에 대한 고찰... (1) | 2009.10.28 |
MSSQL 2005 new Feature - 향상된 분산쿼리 (0) | 2009.10.28 |