Sql 扩展当前查询,计算列

Sql 扩展当前查询,计算列,sql,sql-server-2008-r2,Sql,Sql Server 2008 R2,例如,我的表格如下所示: Name date result A 2012-01-01 1 A 2012-02-01 2 B 2013-01-01 1 ... NAME 1 2 3 2014 2013 2012 TOTAL Person B 4 0 2 6 2 2 10 Person A 2 1

例如,我的表格如下所示:

Name       date      result
 A      2012-01-01     1
 A      2012-02-01     2
 B      2013-01-01     1
         ...
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
举一个完整的例子:

目前,我有一个按人员和年份统计行数的工作查询:

这很完美,但我想要的是2014年的额外信息。我需要计算每个结果的行数。 大概是这样的:

Name       date      result
 A      2012-01-01     1
 A      2012-02-01     2
 B      2013-01-01     1
         ...
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
更好的做法是我给结果列起了一个好名字(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
我尝试添加一些额外的代码,例如:

select @colsResult 
  = STUFF((SELECT  ',' + QUOTENAME(result) 
           from list
           group by result
           order by result
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')
因此,我:

,[1]
,[2]
,[3]

但是如果我运行整个代码,我会得到一个错误,invalid column name…

因为您现在有两个要透视的列,您必须首先取消这些列的PIVOT,然后将这些值转换为新列

从SQLServer2005开始,您可以使用
交叉应用
取消对列的填充。基本语法类似于:

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)
看。此查询将获取名称列表,其中包含“新列”,然后是每个名称的总条目

|     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。但您似乎有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;
看。这就产生了一个结果:

|     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 |
|     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 |
如果只想筛选当前年份的结果列,则可以通过多种方式执行此筛选,但最简单的方法是在unpivot中包含筛选器。硬编码版本为:

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;
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;
看。那么动态sql版本将是:

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;
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;
看。此版本将给出一个结果:

|     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 |
|     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个?谢谢您的回复!这几乎就是我需要的。但我只需要去年的失利、平局和获胜列(2014年的时候…),所以对于B个人来说是4 0 2。