我有一个查询列出了一些有关文档编写器的统计信息:
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
包含的语言多于英语:
English
French
English;French
German
French;German
等。 <{1}}上的不同内容可能会在一周内返回不同的结果,因为有人插入了新值。
我想在我的统计数据中包含所有语言:
#documents.Language
但是,这需要我不时地手动更新查询。我希望在新语言可用时自动更新查询:
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
我怎样才能做到这一点?非常感谢任何帮助,如果它意味着涉及另一个临时表加入(尽管,出于学习目的,我更喜欢动态sql)。
答案 0 :(得分:1)
嗯......因为你准备好了一点点动态SQL ......给它一个旋转:
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; - )
答案 1 :(得分:0)
如果您有SQL 2008及更高版本,则可以使用PIVOT或UNPIVOT。在此处查看更多信息:https://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx