【问题标题】:SQL Server making rows into columnsSQL Server 将行变成列
【发布时间】:2013-09-24 14:28:53
【问题描述】:

我正在尝试获取我拥有的三个表格,并以用户要求我这样做的方式显示数据。桌子看起来像这样。 (我应该补充一点,我使用的是 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。

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

【问题讨论】:

    标签: sql-server tsql pivot


    【解决方案1】:

    您可以通过多种方式获得结果,包括使用 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

    【讨论】:

    • 标记为正确答案。虽然表 2 中的特征是固定数量,但未来可能会更多。因此,我使用了您的第二个解决方案,并且效果很好。非常感谢您的解释和帮助我!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-19
    • 1970-01-01
    • 1970-01-01
    • 2013-05-05
    • 1970-01-01
    • 2023-03-09
    • 1970-01-01
    相关资源
    最近更新 更多