SQL Server 2008垂直数据为水平

Fil*_*ank 14 sql-server transpose pivot

我为提交关于这个主题的另一个问题而道歉,但我已经阅读了很多这方面的答案,我似乎无法让它为我工作.

我有三个表需要加入并提取信息.其中一个表只有3列并垂直存储数据.我想将这些数据转换为横向格式.

如果我只是加入并拉动,数据将如下所示:

SELECT 
   a.app_id, 
   b.field_id, 
   c.field_name,
   b.field_value 
FROM table1 a
JOIN table2 b ON a.app_id = b.app_id
JOIN table3 c ON b.field_id = c.field_id  --(table3 is a lookup table for field names)
Run Code Online (Sandbox Code Playgroud)

结果:

app_id  |  field_id  |   field_name   |  field_value
-----------------------------------------------------
 1234   |    101     |    First Name  |     Joe  
 1234   |    102     |     Last Name  |     Smith
 1234   |    105     |       DOB      |   10/15/72
 1234   |    107     |  Mailing Addr  |   PO BOX 1234
 1234   |    110     |      Zip       |     12345      
 1239   |    101     |    First Name  |     Bob  
 1239   |    102     |     Last Name  |     Johnson
 1239   |    105     |       DOB      |   12/01/78
 1239   |    107     |  Mailing Addr  |   1234 N Star Ave
 1239   |    110     |      Zip       |     12456  
Run Code Online (Sandbox Code Playgroud)

相反,我希望它看起来像这样:

app_id  |  First Name  |   Last Name   |    DOB    |   Mailing Addr   |  Zip
--------------------------------------------------------------------------
 1234   |    Joe       |     Smith     |  10/15/72 |   PO BOX 1234    | 12345     
 1239   |    Bob       |    Johnson    |  12/01/78 |  1234 N Star Ave | 12456 
Run Code Online (Sandbox Code Playgroud)

在过去,我只是在我的数据中查找我需要的所有field_id,并为每个创建CASE语句.用户使用的应用程序包含多个产品的数据,每个产品包含不同的字段.考虑到支持的产品数量和每个产品的字段数量(许多,比我上面显示的基本示例多得多),需要很长时间才能查找并写出大量的CASE语句.

我想知道是否有一些作弊代码可以实现我的需要而无需查看field_ids并编写出来.我知道PIVOT功能可能是我正在寻找的,但是,我似乎无法让它正常工作.

认为你们可以帮忙吗?

Tar*_*ryn 30

您可以使用PIVOT函数将数据行转换为列.

您的原始查询可用于检索所有数据,我将对其进行的唯一更改是排除列,b.field_id因为这将改变结果的最终显示.

如果您有一个已知的field_name值列表要转换为列,则可以对查询进行硬编码:

select app_id,
  [First Name], [Last Name], [DOB],
  [Mailing Addr], [Zip]
from
(
  SELECT 
     a.app_id, 
     c.field_name,
     b.field_value 
  FROM table1 a
  INNER JOIN table2 b 
    ON a.app_id = b.app_id
  INNER JOIN table3 c 
    ON b.field_id = c.field_id 
) d
pivot
(
  max(field_value)
  for field_name in ([First Name], [Last Name], [DOB],
                     [Mailing Addr], [Zip])
) piv;
Run Code Online (Sandbox Code Playgroud)

请参阅SQL Fiddle with Demo.

但是,如果您要使用未知数量的值field_name,则需要实现动态SQL以获得结果:

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

select @cols = STUFF((SELECT ',' + QUOTENAME(Field_name) 
                    from Table3
                    group by field_name, Field_id
                    order by Field_id
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT app_id,' + @cols + ' 
            from 
            (
              SELECT 
                 a.app_id, 
                 c.field_name,
                 b.field_value 
              FROM table1 a
              INNER JOIN table2 b 
                ON a.app_id = b.app_id
              INNER JOIN table3 c 
                ON b.field_id = c.field_id 
            ) x
            pivot 
            (
                max(field_value)
                for field_name in (' + @cols + ')
            ) p '

execute sp_executesql @query;
Run Code Online (Sandbox Code Playgroud)

请参阅SQL Fiddle with Demo.这两个都会产生结果:

| APP_ID | FIRST NAME | LAST NAME |      DOB |    MAILING ADDR |   ZIP |
------------------------------------------------------------------------
|   1234 |        Joe |     Smith | 10/15/72 |     PO Box 1234 | 12345 |
|   1239 |        Bob |   Johnson | 12/01/78 | 1234 N Star Ave | 12456 |
Run Code Online (Sandbox Code Playgroud)

  • 这正是我所需要的.我没有代表赞成你,但如果有人在这里看到这个,请为我投票! (4认同)