2016-07-18 2 views
1

두 개의 CTE가 있습니다. 첫 번째 레코드는 'select top n'을 실행하여 레코드 샘플을 얻은 다음 두 번째 레코드는 각 레코드에 대해 2 개의 행을 생성합니다.CTE가 두 번 선택을 실행하는 이유는 무엇입니까?

샘플의 정렬 순서를 결정하기 위해 newid()를 사용하여 가짜 데이터로 재생했습니다.

Pos Id Col 
0 720 A719 
1 720 A719 

그러나, 내가 무엇을 얻을 것은

Pos Id Col 
0 720 A719 
1 774 B773 
그래서

은 "상위 1"같은 것이 있습니다 :

declare @testtab table (Id bigint identity (1,1), ColA varchar(10), ColB varchar(10)) 
-- generate 1000 sample records 
declare @cnt int = 0 
while (@cnt<1000) 
begin 
    insert @testtab(ColA, ColB) values ('A'+convert(varchar,@cnt), 'B'+convert(varchar,@cnt)) 
    set @cnt+=1 
end 

;with SampleRecs as(
select top 1 * from @testtab order by newid() 
) 
,SplitRecs as (
select 0 Pos,Id,ColA Col from SampleRecs 
union all 
select 1, id, ColB col from SampleRecs 
) 
select * from SplitRecs 
order by id, pos 

예상되는 최종 결과는 각 입력 행에 대해 2 개 행이는 같은 것입니다 CTE 2에서 CTE가 두 번 실행되는 것 같습니다.

정상입니까? 누구든지이 동작을 설명 할 수있는 문서를 가리킬 수 있습니까?

+1

:

하면 기대하고있는 결과를 얻으려면, 당신은 다음 대신하는이 CROSS JOINPos 값을 시드 활용 할 수 그래서 상위 1 위를 차지하고 상위 1 위를 노조하고 2 개의 결과를 얻습니다. – Matt

답변

3

CTE에서 두 번째로 첫 번째 CTE을 두 번째로 참조하기 때문입니다. UNION ALL.

은 본질적으로 임시보기이며 호출 된 후에는 무시됩니다. 따라서 첫 번째 CTE을 호출 할 때 SELECT 문을 별도로 실행하고 ORDER BYNEWID() 이상이므로 두 사례 모두 다른 TOP 1 결과를 얻을 수 있습니다.

SampleRecs는 다음과 같이 정의된다 : 실제 문을 쿼리에서 CTE 참조를 교체

무슨 일이 일어나고 있는지 설명하는 데 도움이

선택 상위 1 * (NEWID에 의해 @testtab 순서에서)

그래서 하위 쿼리에 대한 모든 참조를 대체, 다음 당신에게 줄 것이다 :

;With SplitRecs As 
(
    Select 0  As Pos, 
      Id, 
      ColA As Col 
    From (Select Top 1 * From @testtab Order By NewId()) As A 
    Union All 
    Select 1  As Pos, 
      Id, 
      ColB As Col 
    From (Select Top 1 * From @testtab Order By NewId()) As B 
) 
Select * 
From SplitRecs 
Order By Id, pos 

CTE 변형과 마찬가지로이 동작을 수행하게됩니다. 당신이 선택하는 CTE는 UNION을 모두 가지고있는 splitrecs 때문에

Select  X.Pos As Pos, 
      Id, 
      ColA As Col 
From  (Select Top 1 * From @testtab Order By NewId()) As A 
Cross Join (Select 0 As Pos Union All Select 1) As X 
Order By X.Pos 
+0

그러면 CTE가 매우 비효율적입니까? 편리하고, 그렇지만 비효율적입니다. 임시 테이블을 삭제하는 문제를 해결하는 것이 좋습니다. 다양한 articels에 묘사 된 방식에서 나는 CTE가 임시 테이블과 동일하다는 인상을 항상 받고있었습니다. 그러나 이것은 매우 중요한 차이입니다. – user6604437