-2

我在 SQLServer 表中有这样的数据:

ID   Name   Year   Value
--   ----   ----   -----
2    Ted    2013   2000
2    Ted    2012   1000

我需要视图语法来输出这个:

ID    Name    Yr1    Value1    Yr2    Value2
--    ----    ---    ------    ---    ------ 
2     Ted     2013   2000      2012   1000

如果可能,不要使用游标。任何线索都会很棒。

4

1 回答 1

3

在 SQL Server 中,您可以通过多种方式获得结果。

如果您的值数量有限,那么您可以轻松地对结果进行硬编码。获得结果的一种方法是使用带有 CASE 表达式的聚合函数:

select d.id,
  d.name,
  max(case when seq = 1 then year end) year1,
  max(case when seq = 1 then value end) value1,
  max(case when seq = 2 then year end) year2,
  max(case when seq = 2 then value end) value2
from
(
  select id, name, year, value,
    row_number() over(partition by id order by year desc) seq
  from yourtable
) d
group by d.id, d.name;

请参阅SQL Fiddle with Demo。如果你想使用PIVOT函数,那么我建议首先取消透视yearvalue列中的数据。unpivot 过程将多列转换为多行。您可以使用 UNPIVOT 函数,但在我的示例中,我将 CROSS APPLY 与 UNION ALL 查询一起使用,代码为:

select t.id, t.name, 
  col = c.col+cast(seq as varchar(4)), 
  c.val
from
(
  select id, name, year, value,
    row_number() over(partition by id order by year desc) seq
  from yourtable
) t
cross apply
(
  select 'year', t.year union all
  select 'value', t.value 
) c (col, val)

请参阅SQL Fiddle with Demo。这会将您的多列转换为具有多行的稍微不同的格式:

| ID | NAME |    COL |  VAL |
|  2 |  Ted |  year1 | 2013 |
|  2 |  Ted | value1 | 2000 |
|  2 |  Ted |  year2 | 2012 |
|  2 |  Ted | value2 | 1000 |

然后,您可以在此应用 PIVOT 函数以获得最终所需的结果:

select id, name, year1, value1, year2, value2
from 
(
  select t.id, t.name, 
    col = c.col+cast(seq as varchar(4)), 
    c.val
  from
  (
    select id, name, year, value,
      row_number() over(partition by id order by year desc) seq
    from yourtable
  ) t
  cross apply
  (
    select 'year', t.year union all
    select 'value', t.value 
  ) c (col, val)
) d
pivot
(
  max(val)
  for col in (year1, value1, year2, value2)
) piv;

请参阅SQL Fiddle with Demo。最后,如果您想将未知数量的值从行转换为列,则可以在存储过程中使用动态 SQL:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT  ',' + QUOTENAME(col+cast(seq as varchar(4))) 
                    from 
                    (
                      select row_number() over(partition by id order by year desc) seq
                      from yourtable
                    ) d
                    cross apply 
                    (
                      select 'year', 1 union all
                      select 'value', 2
                    ) c (col, so)
                    group by seq, col, so
                    order by seq, so
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = 'SELECT id, name,' + @cols + ' 
             from 
             (
               select t.id, t.name, 
                  col = c.col+cast(seq as varchar(4)), 
                  c.val
                from
                (
                  select id, name, year, value,
                    row_number() over(partition by id order by year desc) seq
                  from yourtable
                ) t
                cross apply
                (
                  select ''year'', t.year union all
                  select ''value'', t.value 
                ) c (col, val)
            ) x
            pivot 
            (
                max(val)
                for col in (' + @cols + ')
            ) p '

execute sp_executesql @query;

请参阅SQL Fiddle with Demo。所有版本都会给出一个结果:

| ID | NAME | YEAR1 | VALUE1 | YEAR2 | VALUE2 |
|  2 |  Ted |  2013 |   2000 |  2012 |   1000 |
于 2013-08-26T22:45:48.713 回答