SQL Server将行放入列中

时间:2013-09-24 14:28:53

标签: sql-server tsql pivot

我正在尝试使用我拥有的三个表,并以用户要求我这样做的方式显示数据。表格看起来像这样。 (我应该补充说我正在使用MS SQL Server)

第一张表:ID是varchar,因为它是用于识别资产的ID,它们使用数字和字母。

    aID| status | group   |
    -----------------------
    1  |   acti |  group1 |
    2  |   inac |  group2 |
   A3  |   acti |  group1 |

第二张表:此表已修复。它有大约20个值,ID都是数字

    atID| traitname  |
    ------------------
     1  |   trait1   |
     2  |   trait2   |
     3  |   trait3   |

第三表:该表用于识别第一个表中资产的特征。与上表中的字段同名的字段显然是链接的。

tID|   aID  |   atID |   trait   |
----------------------------------
1  |   1    |    1   |   NAME    |
2  |   1    |    2   |   INFO    |
3  |   2    |    3   |   GOES    |
4  |   2    |    1   |   HERE    |
5  |   A3   |    2   |   HAHA    |

现在,用户希望程序以下列格式输出数据:

aID| status | group  | trait1 | trait2 | trait 3
-------------------------------------------------
1  |  acti  |  group1 |  NAME |  INFO  | NULL
2  |  inac  |  group2 |  HERE |  NULL  | GOES
A3 |  acti  |  group1 |  NULL |  HAHA  | NULL

我明白要实现这一点,我必须在SQL中使用Pivot命令。但是,我已阅读并试图理解它,但我似乎无法得到它。特别是它要求MAX值的部分。我不明白为什么我需要那个MAX。

此外,我见过的例子是一张桌子。我不确定我是否可以用三张桌子来做。我确实有一个查询,将所有这三个与我需要的信息连接起来。但是,我不知道如何从那里开始。对此,任何帮助将不胜感激。谢谢。

1 个答案:

答案 0 :(得分:4)

有几种方法可以获得结果,包括使用PIVOT功能。

您可以将聚合函数与CASE表达式一起使用:

select t1.aid, t1.status, t1.[group],
  max(case when t2.traitname = 'trait1' then t3.trait end) trait1,
  max(case when t2.traitname = 'trait2' then t3.trait end) trait2,
  max(case when t2.traitname = 'trait3' then t3.trait end) trait3
from table1 t1
inner join table3 t3
  on t1.aid = t3.aid
inner join table2 t2
  on t3.atid = t2.atid
group by t1.aid, t1.status, t1.[group];

请参阅SQL Fiddle with Demo

PIVOT函数需要一个聚合函数,这就是你需要使用MIN或MAX函数的原因(因为你有一个字符串值)。

如果您的traitnames数量有限,那么您可以对查询进行硬编码:

select aid, status, [group],
  trait1, trait2, trait3
from
(
  select t1.aid,
    t1.status,
    t1.[group],
    t2.traitname,
    t3.trait
  from table1 t1
  inner join table3 t3
    on t1.aid = t3.aid
  inner join table2 t2
    on t3.atid = t2.atid
) d
pivot
(
  max(trait)
  for traitname in (trait1, trait2, trait3)
) piv;

SQL Fiddle with Demo

如果您有未知数量的值,那么您将需要查看使用动态SQL来获得最终结果:

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

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(traitname) 
                    from Table2
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT aid, status, [group],' + @cols + ' 
            from 
            (
              select t1.aid,
                t1.status,
                t1.[group],
                t2.traitname,
                t3.trait
              from table1 t1
              inner join table3 t3
                on t1.aid = t3.aid
              inner join table2 t2
                on t3.atid = t2.atid
            ) x
            pivot 
            (
                max(trait)
                for traitname in (' + @cols + ')
            ) p '

execute sp_executesql @query;

请参阅SQL Fiddle with Demo