end*_*eka -2 sql sql-server-2008-r2
我的表看起来像这样的例子:
Name date result
A 2012-01-01 1
A 2012-02-01 2
B 2013-01-01 1
...
Run Code Online (Sandbox Code Playgroud)
有关完整示例:http://sqlfiddle.com/#!3/00222/1
目前我有一个工作查询,按人和年计算行数:http://sqlfiddle.com/#!3/00225/32
这是完美的,但我想要的是2014年的一些额外信息.我需要计算每个结果我有多少行.这样的事情:
NAME 1 2 3 2014 2013 2012 TOTAL
Person B 4 0 2 6 2 2 10
Person A 2 1 1 4 3 4 11
Person C 1 1 1 3 1 0 4
Run Code Online (Sandbox Code Playgroud)
更好的是我给结果列一个好名字(1 =丢失,2 =抽奖,3 =赢):
NAME lost draw won 2014 2013 2012 TOTAL
Person B 4 0 2 6 2 2 10
Person A 2 1 1 4 3 4 11
Person C 1 1 1 3 1 0 4
Run Code Online (Sandbox Code Playgroud)
我试图添加一些额外的代码,例如:
select @colsResult
= STUFF((SELECT ',' + QUOTENAME(result)
from list
group by result
order by result
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
Run Code Online (Sandbox Code Playgroud)
我有结果:
,[1]
,[2]
,[3]
Run Code Online (Sandbox Code Playgroud)
但如果我运行整个代码我得到一个错误,invallid列名...
由于您有两列现在想要PIVOT,因此首先必须取消这些列的转换,然后将这些值转换为新列.
从SQL Server 2005开始,您可以使用CROSS APPLY
以取消对列的拆分.基本语法类似于:
select
name,
new_col,
total
from
(
select name,
dt = year(date),
result,
total = count(*) over(partition by name)
from list
) d
cross apply
(
select 'dt', dt union all
select 'result', result
) c (old_col_name, new_col)
Run Code Online (Sandbox Code Playgroud)
请参阅SQL Fiddle with Demo.此查询将为您提供名称列表,其中包含"新列",然后是每个名称的"总计"条目.
| NAME | NEW_COL | TOTAL |
|----------|---------|-------|
| Person A | 2012 | 11 |
| Person A | 1 | 11 |
| Person A | 2012 | 11 |
| Person A | 2 | 11 |
Run Code Online (Sandbox Code Playgroud)
您会看到日期和结果现在都存储在"new_col"中.这些值现在将用作新列名.如果您的列数有限,那么您只需对查询进行硬编码:
select name, lost = [1],
draw=[2], won = [3],
[2014], [2013], [2012], Total
from
(
select
name,
new_col,
total
from
(
select name,
dt = year(date),
result,
total = count(*) over(partition by name)
from list
) d
cross apply
(
select 'dt', dt union all
select 'result', result
) c (old_col_name, new_col)
) src
pivot
(
count(new_col)
for new_col in([1], [2], [3], [2014], [2013], [2012])
) piv
order by [2014];
Run Code Online (Sandbox Code Playgroud)
既然你的岁月是动态的,那么你需要使用动态的sql.但是看起来你有3个结果并且可能有多年 - 所以我会使用静态/动态sql的组合来使这更容易:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX),
@orderby nvarchar(max)
select @cols
= STUFF((SELECT ',' + QUOTENAME(year(date))
from list
group by year(date)
order by year(date) desc
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select @orderby = 'ORDER BY ['+cast(year(getdate()) as varchar(4)) + '] desc'
set @query = 'SELECT name, lost = [1],
draw=[2], won = [3],' + @cols + ', Total
from
(
select
name,
new_col,
total
from
(
select name,
dt = year(date),
result,
total = count(*) over(partition by name)
from list
) d
cross apply
(
select ''dt'', dt union all
select ''result'', result
) c (old_col_name, new_col)
) x
pivot
(
count(new_col)
for new_col in ([1], [2], [3],' + @cols + ')
) p '+ @orderby
exec sp_executesql @query;
Run Code Online (Sandbox Code Playgroud)
请参阅SQL Fiddle with Demo.这给出了一个结果:
| NAME | LOST | DRAW | WON | 2014 | 2013 | 2012 | TOTAL |
|----------|------|------|-----|------|------|------|-------|
| Person B | 7 | 1 | 2 | 6 | 2 | 2 | 10 |
| Person A | 5 | 3 | 3 | 4 | 3 | 4 | 11 |
| Person C | 2 | 1 | 1 | 3 | 1 | 0 | 4 |
Run Code Online (Sandbox Code Playgroud)
如果你想只筛选本年度的结果列,然后才能执行此过滤多种方式,但你可以包括在逆转置过滤器最简单的.硬编码版本将是:
select name, lost = [1],
draw=[2], won = [3],
[2014], [2013], [2012], Total
from
(
select
name,
new_col,
total
from
(
select name,
dt = year(date),
result,
total = count(*) over(partition by name)
from list
) d
cross apply
(
select 'dt', dt union all
select 'result', case when dt = 2014 then result end
) c (old_col_name, new_col)
) src
pivot
(
count(new_col)
for new_col in([1], [2], [3], [2014], [2013], [2012])
) piv
order by [2014] desc;
Run Code Online (Sandbox Code Playgroud)
请参阅SQL Fiddle with Demo.那么动态的sql版本将是:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX),
@orderby nvarchar(max),
@currentYear varchar(4)
select @currentYear = cast(year(getdate()) as varchar(4))
select @cols
= STUFF((SELECT ',' + QUOTENAME(year(date))
from list
group by year(date)
order by year(date) desc
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select @orderby = 'ORDER BY ['+ @currentYear + '] desc'
set @query = 'SELECT name, lost = [1],
draw=[2], won = [3],' + @cols + ', Total
from
(
select
name,
new_col,
total
from
(
select name,
dt = year(date),
result,
total = count(*) over(partition by name)
from list
) d
cross apply
(
select ''dt'', dt union all
select ''result'', case when dt = '+@currentYear+' then result end
) c (old_col_name, new_col)
) x
pivot
(
count(new_col)
for new_col in ([1], [2], [3],' + @cols + ')
) p '+ @orderby
exec sp_executesql @query;
Run Code Online (Sandbox Code Playgroud)
请参阅SQL Fiddle with Demo.这个版本会给出一个结果:
| NAME | LOST | DRAW | WON | 2014 | 2013 | 2012 | TOTAL |
|----------|------|------|-----|------|------|------|-------|
| Person B | 4 | 0 | 2 | 6 | 2 | 2 | 10 |
| Person A | 2 | 1 | 1 | 4 | 3 | 4 | 11 |
| Person C | 1 | 1 | 1 | 3 | 1 | 0 | 4 |
Run Code Online (Sandbox Code Playgroud)