【问题标题】:T-SQL Transposing column headers into RowsT-SQL 将列标题转换为行
【发布时间】:2014-11-08 11:56:37
【问题描述】:

我想转置我的表格。 我有简单的“人”表,如下所示。

+---+----------+------------+------------+----------------------+
|ID | Person   | BirthDate  | Phone      | Email                |
+---+----------+------------+------------+----------------------+
| 1 | Tom      | 1985-11-08 | 1111111111 | tom@somedomain.com   |
+---+----------+------------+------------+----------------------+
| 2 | Dick     | 1982-02-24 | 2222222222 | dick@otherdomain.com |
+---+----------+------------+------------+----------------------+
| 3 | Harry    | 1986-04-17 | 3333333333 | harry@thatdomain.com |
+---+----------+------------+------------+----------------------+

我希望这张表像下面这样转置。

+-----------+--------------------+----------------------+----------------------+
| Key       | Value1             | Value2               | Value3               |
+-----------+--------------------+----------------------+----------------------+
| ID        | 1                  | 2                    | 3                    |
+-----------+--------------------+----------------------+----------------------+
| Person    | Tom                | Dick                 | Harry                |
+-----------+--------------------+----------------------+----------------------+
| BirthDate | 1985-11-08         | 1982-02-24           | 1986-04-17           |
+-----------+--------------------+----------------------+----------------------+
| Phone     | 1111111111         | 2222222222           | 3333333333           |
+-----------+--------------------+----------------------+----------------------+
| Email     | tom@somedomain.com | dick@otherdomain.com | harry@thatdomain.com |
+-----------+--------------------+----------------------+----------------------+

我正在使用 MS SQL Server 2008 R2。

【问题讨论】:

    标签: sql-server sql-server-2008 sql-server-2008-r2 pivot


    【解决方案1】:

    试试这个.. 首先你需要unpivot 使用Cross apply 的列来获取单行中的数据。然后pivot该行得到结果。

    CREATE TABLE #tt
      (ID        INT,Person    VARCHAR(50),BirthDate DATE,
         Phone     BIGINT,Email     VARCHAR(50)
      )
    
    INSERT INTO #tt
    VALUES      (1,'Tom','1985-11-08',1111111111,'tom@somedomain.com' ),
                ( 2,'Dick','1982-02-24',2222222222,'dick@otherdomain.com'),
                ( 3,'Harry ','1986-04-17',3333333333,'harry@thatdomain.com' ) 
    
    SELECT [key],
           Max([value1]) [value1],
           Max([value2]) [value2],
           Max([value3]) [value3]
    FROM   (SELECT 'value' + CONVERT(VARCHAR(30), id) valued,
                   *
            FROM   #tt
                   CROSS apply (VALUES ('ID',
                               CONVERT(VARCHAR(50), ID)),
                                       ('Person',Person),
                                       ('BirthDate',CONVERT(VARCHAR(50), BirthDate)),
                                       ('Phone',CONVERT(VARCHAR(50), Phone)),
                                       ('Email',Email)) cp ([key], data))a
           PIVOT (Max(data)
                 FOR valued IN([value1],[value2],[value3])) piv
    GROUP  BY [key] 
    

    动态版本

    Declare @cols varchar(max)='',@aggcols varchar(max)='',@sql nvarchar(max)
    
    SELECT @cols+= ',value' + CONVERT(VARCHAR(30), id) 
            FROM   #tt
    SELECT @aggcols+= ',max([value' + CONVERT(VARCHAR(30), id) +']) value' + CONVERT(VARCHAR(30), id) 
            FROM   #tt
    select @cols=  right(@cols,LEN(@cols)-1)
    select @aggcols =right(@aggcols,LEN(@aggcols)-1)
    
    
    set @sql = 'SELECT [key],
           '+@aggcols+'
    FROM   (SELECT ''value'' + CONVERT(VARCHAR(30), id) valued,
                   *
            FROM   #tt
                   CROSS apply (VALUES (''ID'',CONVERT(VARCHAR(50), ID)),
                                       (''Person'',Person),
                                       (''BirthDate'',CONVERT(VARCHAR(50), BirthDate)),
                                       (''Phone'',CONVERT(VARCHAR(50), Phone)),
                                       (''Email'',Email)) cp ([key], data))a
           PIVOT (Max(data)
                 FOR valued IN('+@cols+')) piv
    GROUP  BY [key] '
    
    execute sp_executesql @sql
    

    输出

    +----------+--------------------+---------------------+----------------------+
    |key       |    value1          |   value2            |     value3           |
    +----------+--------------------+---------------------+----------------------+
    |BirthDate |    1985-11-08      |   1982-02-24        |     1986-04-17       |
    +----------+--------------------+---------------------+----------------------+
    |Email     | tom@somedomain.com |dick@otherdomain.com | harry@thatdomain.com |
    +----------+--------------------+---------------------+----------------------+
    |ID        |    1               |   2                 |     3                |
    +----------+--------------------+---------------------+----------------------+
    |Person    |    Tom             |   Dick              |     Harry            |
    +----------+--------------------+---------------------+----------------------+
    |Phone     |    1111111111      |   2222222222        |     3333333333       |
    +----------+--------------------+---------------------+----------------------+
    

    【讨论】:

    • 感谢您的解决方案。有没有办法让这个动态?我的意思是当新记录进入第一个表时,我们可以有那么多列吗?
    • 使用 STUFF 接受所有列名,并通过动态查询执行它。也许这篇文章会对你有所帮助Efficiently convert rows to columns in sql server
    猜你喜欢
    • 1970-01-01
    • 2017-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-06
    • 2021-02-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多