SQL使用相同的表加入数据透视表

时间:2017-05-12 16:56:30

标签: sql-server sql-server-2008 tsql

我有一个问题,我正在尝试加入同一个表并创建它的列。例如,该表包含idnametype

数据可以是:

id          name            type            Date 
--------------------------------------------------
1           KKKK            BP          05/05/2017 
2           MMMM            KS          07/10/2016 
3           LLL             TL          04/05/2017 
4           NNN             BP          06/01/2016

我想制作一个包含以下设计的表格:

- id   name      BP                 KS                   TL  
-------------------------------------------------------------
1      KKK    05/05/2017 
2      MMM                       07/10/2016  
3      LLL                                           04/05/2017 
4      NNN    06/01/2017

我尝试了Pivot表并且没有工作。

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

您可以使用SQL Server 2008中的PIVOT函数将数据行转换为列:

select 
  id,
  name,
  BP, KS, TL
from
(
  select id, 
    name,
    type,
    [date]
  from mytable
) d
pivot
(
  max([date])
  for type in (BP, KS, TL)
) piv;

这也可以使用条件逻辑编写,例如带有一些聚合的CASE表达式:

select id,
  name,
  BP = max(case when type = 'BP' then [date] end),
  KS = max(case when type = 'KS' then [date] end),
  TL = max(case when type = 'TL' then [date] end)
from mytable
group by id, name;

根据您的评论,您可以为每个nametype组合设置多个日期,您仍然可以使用类似的查询来使用像row_number这样的窗口函数得到你想要的最终结果。

如果要使用条件逻辑版本,则需要将查询更改为:

select 
  name,
  BP1 = max(case when type = 'BP' and rn =1 then [date] end),
  BP2 = max(case when type = 'BP' and rn =2 then [date] end),
  BP3 = max(case when type = 'BP' and rn =3 then [date] end),
  KS1 = max(case when type = 'KS' and rn =1 then [date] end),
  KS2 = max(case when type = 'KS' and rn =2 then [date] end),
  TL1 = max(case when type = 'TL' and rn =1 then [date] end)
from 
(
  select 
    name,
    [type], 
    [date],
    rn = row_number() over(partition by name, [type] order by [date] desc)
  from mytable
) d
group by name;

PIVOT版本将是:

select 
  name,
  BP1, BP2, BP3, KS1, KS2, TL1
from
(
  select 
    name,
    type = type + cast(rn as varchar(2)),
    [date]
  from
  (
    select 
      name,
      type,
      [date],
      rn = row_number() over(partition by name, [type] order by [date] desc)
    from mytable
  )s
) d
pivot
(
  max([date])
  for type in (BP1, BP2, BP3, KS1, KS2, TL1)
) piv;

正如您所看到的,有很多类型可以获取所有这些列,因此您可以使用动态SQL来获得最终结果:

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

select @cols = STUFF((SELECT ',' + QUOTENAME(Type + cast(rn as varchar(2))) 
                    from
                    (
                      select type,
                        rn = row_number() over(partition by name, type order by date desc)
                      from mytable
                    ) d
                    group by type, rn
                    order by type, rn
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = N'SELECT name, ' + @cols + N' 
            from 
            (
                select 
                  name,
                  type = type + cast(rn as varchar(2)),
                  [date]
                from
                (
                  select 
                    name,
                    type,
                    [date],
                    rn = row_number() over(partition by name, [type] order by [date] desc)
                  from mytable
                )s
            ) x
            pivot 
            (
                max(date)
                for type in (' + @cols + N')
            ) p '

exec sp_executesql @query;

我创建了一个demo来表明它们都返回相同的结果。