2016-06-08 3 views
2

나는 문서 작가에 대한 몇 가지 통계를 나열하는 쿼리가 : 현실에서쿼리에 동적 개수의 열을 추가하려면 어떻게합니까?

select d.WrittenBy, 
     count(1) as NumDocs, 
     sum(case when d.Language = 'English' then 1 else 0 end) as English, 
     sum(case when d.Published = 1 then 1 else 0 end) as NumPublished 
from  #documents d 
group by d.WrittenBy 

#documents.Language는 영어보다 더 많은 언어를 포함

#documents.Language에 등 뚜렷한
English 
French 
English;French 
German 
French;German 

는 다른 결과를 반환 할 수 있습니다 지금부터 누군가가 새로운 가치관을 삽입했기 때문에 1 주일 후에

내 통계에 모든 언어를 포함시킬 :

select d.WrittenBy, 
     count(1) as NumDocs, 
     sum(case when d.Language = 'English' then 1 else 0 end) as English, 
     sum(case when d.Language = 'French' then 1 else 0 end) as French, 
     sum(case when d.Language = 'English;French' then 1 else 0 end) as EnglishFrench, 
     ... 
     ... 
     sum(case when d.Published = 1 then 1 else 0 end) as NumPublished 
from  #documents d 
group by d.WrittenBy 

그러나이 수동으로 모든 이제 다음 쿼리를 업데이트 할 저를 필요로한다. 새로운 언어를 사용할 수있게되면 내가 대신 자동으로 쿼리 업데이트를하고 싶은 :

declare @cols as nvarchar(max); 

set @cols = stuff 
    (
     (
      select distinct ',' + quotename(Language) 
      from #documents 
      for xml path(''), type 
     ).value('.', 'nvarchar(max)'), 1, 1, '' 
    ) 

이 나에게 가능한 모든 Languages의 목록을 제공합니다. 그리고 여기 나는 갇혀있다. 테이블에 다음 언어 열을 동적으로 추가하고 싶습니다.

WrittenBy NumDocs English French EnglishFrench ... Numpublished 
----------------------------------------------------------------------- 
Linda   10  5  2   1  ...  4 
Peter   8  0  0   6  ...  0 

어떻게하면됩니까? 어떤 도움을 주셔서 감사합니다. 또한 다른 임시 테이블이 참여하는 것을 의미하는 경우 (학습 목적을 위해 동적 SQL을 선호하지만).

답변

1

음을 ...에 ...이에게 돌리기 제공 : 나는 설명 할 것이다

set nocount on 
declare 
    @sql nvarchar(max), 
    @expression nvarchar(max), 
    @template nvarchar(256), 
    @language nvarchar(128) 

select @expression = ''; 

declare c cursor for select distinct language from #documents 
open c 
    while (1 = 1) 
    begin 
     fetch next from c into @language 
     if (@@fetch_status != 0) break 
     select @template = 'sum(case when d.Language = '''+ @language +''' then 1 else 0 end) as ' + replace(@language,';','') 
     select @expression += @template + ',' 
    end 
close c 
deallocate c 

select @sql = 
'select 
    d.WrittenBy, 
    count(1) as NumDocs, 
    '+ @expression +' 
    sum(case when d.Published = 1 then 1 else 0 end) as NumPublished 
from  #documents d 
group by d.WrittenBy' 

execute (@sql) 

하나의 작은 트릭을 ... 루프를 시작하기 전에 @expression을 빈 문자열로 초기화해야합니다. 그렇지 않으면 null이되고 null을 추가하면 null이됩니다.

+0

Thanks @Clay! 나는 직장에 복귀하자마자 이것을 시도 할 것이다. 한 가지 질문 - 'while (1 = 1)'에 대해 설명해 주시겠습니까? 1은 항상 1이므로,이 루프가 영원히 지속될 것으로 기대합니다. 그러나 한 점에서'@@ fetch_status'가 0이 아니기 때문에 그럴 수 없습니다. 그렇다면이 문맥에서'1 = 1'을 어떻게 해석할까요? – Pr0no

+1

당신은 맞습니다. 그것은 단지 "영원한 루프"입니다 ... 조건은 항상 사실 일 것입니다. tsql에는 'while (true)'이 없습니다. 데이터가 없어지면 루프를 종료하는 것은 if (@@ fetch_status! = 0) 중단입니다. – Clay

관련 문제