既然你有两列,你现在要枢,你首先必须unpivot的那些列,然后将这些值转换为新列。
从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)
请参阅SQL Fiddle with Demo。该查询会为您提供一个名称列表,其中包含“新列”,然后是每个名称的Total条目。
| NAME | NEW_COL | TOTAL |
|----------|---------|-------|
| Person A | 2012 | 11 |
| Person A | 1 | 11 |
| Person A | 2012 | 11 |
| Person A | 2 | 11 |
您会看到日期和结果现在都存储在“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];
见SQL Fiddle with Demo
现在,因为你的年是动态的,那么你就需要使用动态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;
见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 |
如果你想只筛选本年度的结果列,然后才能执行此过滤多种方式,但最简单的,你可以包括在逆转置过滤器。硬编码版本将为:
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;
请参阅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 = '[email protected]+' 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;
请参阅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 |
最后一列是否需要特定顺序 - 意味着结果值升序和年降序?你只有3个结果值?它总是会被限制在3? – Taryn 2014-09-11 11:48:28