7

TSQL 问题在这里。请参阅下图中的源和所需输出。还提供了构建源表的代码。

在此处输入图像描述


DECLARE @tablevar TABLE(
record nvarchar(10),
category nvarchar(50),
value float)

INSERT INTO @tablevar
VALUES
('110-AL','credits_cle',1),
('110-AL','credits_ethics',2),
('110-AR','credits_ethics',2.5),
('110-AZ','credits_prof_resp',1.5),
('110-AZ', 'credits_ethics',5),
('110-AZ', 'credits_cle',4)
4

3 回答 3

5

由于您想要 PIVOT 两列数据,因此您可以执行此操作的一种方法是同时应用 UNPIVOT 和 PIVOT 函数。UNPIVOT 会将多列categoryvalue多行转换,然后您可以应用 PIVOT 来获得最终结果:

select record, 
  category1, value1, 
  category2, value2, 
  category3, value3
from
(
  select record, col+cast(seq as varchar(10)) col, val
  from
  (
    select record, category, 
      cast(value as nvarchar(50)) value,
      row_number() over(partition by record order by category) seq
    from tablevar
  ) d
  unpivot
  (
    val
    for col in (category, value)
  ) unpiv
) src
pivot
(
  max(val)
  for col in (category1, value1, category2, value2, category3, value3)
) 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(10))) 
                    from
                    (
                      select row_number() over(partition by record order by category) seq
                      from tablevar
                    ) d
                    cross apply
                    (
                      select 'category', 1 union all
                      select 'value', 2
                    ) c (col, so)
                    group by seq, so, col
                    order by seq, so
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = 'SELECT record,' + @cols + ' 
             from 
             (
               select record, col+cast(seq as varchar(10)) col, val
                from
                (
                  select record, category, 
                    cast(value as nvarchar(50)) value,
                    row_number() over(partition by record order by category) seq
                  from tablevar
                ) d
                unpivot
                (
                  val
                  for col in (category, value)
                ) unpiv
            ) x
            pivot 
            (
                max(val)
                for col in (' + @cols + ')
            ) p '

execute(@query);

请参阅带有演示的 SQL Fiddle

于 2013-06-27T23:04:59.310 回答
2

这是我的尝试

;with Z as
(
select record, category, value,  ROW_NUMBER() over (partition by record order by category) as ranker
from @tablevar
) 
select Z2.record, Z2.c1, Z3.v1, Z2.c2, Z3.v2, Z2.c3, Z3.v3 from 
(
select  record, [1] c1, [2] c2, [3] c3 from 
(select record, category, ranker from Z) as Z0
pivot
( min(category) for ranker in ([1], [2], [3])) as pvt
) Z2

join
(
select  record, [1] v1, [2] v2, [3] v3 from 
(select record, value, ranker from Z) as Z1
pivot
( min(value) for ranker in ([1], [2], [3])) as pvt
) Z3 
on Z2.record = Z3.record
于 2013-06-27T22:44:11.807 回答
2

这是我第一次使用 PIVOT,代码可能非常难看。开始:

with ranked as (
    select *, RANK() OVER (PARTITION by record ORDER by category) as r
    from @tablevar
), labeled as (
    select record, category as content, 'category' + CAST(r as varchar(MAX)) as label
     from ranked
    union all
    select record, cast(value AS nvarchar(MAX)),  'value' + CAST(r as varchar(MAX)) as label
     from ranked) --select * from labeled
select record, [category1] as [category], [value1] as [value], [category2] as [category], [value2] as [value], [category3] as [category], [value3] as [value]
from (SELECT * FROM labeled) as source
PIVOT(
    max(content)
    for label in ([category1], [value1], [category2], [value2], [category3], [value3])) as pvt
于 2013-06-27T22:37:26.977 回答