将2列多行转换为1列多列

时间:2014-02-20 15:04:13

标签: sql sql-server

我试图将下表(示例)转换为1行,其中列名是行列1之一,行的值将对应列2row [x]。

Table

|--------------------------------|
|   ID  |     Key     |   Value  |
|--------------------------------|
|   1   |  'Color'    |    '13'  |
|   1   |  'Access'   |    'H'   |
|   1   |  'LastCalc' |  '17.06' |
|   2   |  'Choice'   |  'done'  |
|   2   |   'timeA'   |  '15:43' |
|--------------------------------|

现在我需要选择每个ID

选择ID 1会给我

|------------------------|
|     Key     |   Value  |
|------------------------|
|  'Color'    |    '13'  |
|  'Access'   |    'H'   |
|  'LastCalc' |  '17.06' |   
|------------------------|

但我需要

|--------------------------------|
| Color |   Access  |  LastCalc  |
|--------------------------------|
|  '13' |    'H'    |   '17.06'  |
|--------------------------------|

使用该方法创建的列数量不会超过300列,因为我有另一列,以确保查询将按300的子集进行查询,并为同一ID创建多个行。

有人做过吗?我有搜索,但我发现的一切都是为了修复列数,并没有做我想要的。也许我没有使用正确的搜索关键字。

1 个答案:

答案 0 :(得分:0)

测试数据

CREATE TABLE Test_Table_P(ID INT,[Key] VARCHAR(100),Value  VARCHAR(100))
INSERT INTO Test_Table_P VALUES
(1,'Color','13'),(1,'Access','H'),   (1,'LastCalc','17.06'),
(2,'Choice','done'),(2,'timeA','15:43')

<强>查询

假设您有一个变量@ID,您想要所有列。

DECLARE @ID INT = 1;

获取给定ID的列,因为对于每个给定的ID,它将是不同的,您需要以[col1],[col2],[col3],.....的格式对列名进行以下操作,这是Pivot语法所必需的。

DECLARE @Cols NVARCHAR(MAX);

SELECT @Cols =  STUFF((SELECT ', ' + [Key] [text()]
                     FROM Test_Table_P
                     WHERE ID = t.ID    
                     FOR XML PATH(''), TYPE).value('.','NVARCHAR(MAX)')
                      ,1, 2, '')
FROM Test_Table_P t
WHERE ID = @ID
GROUP BY t.ID

将列存储在@Cols变量中后,现在可以创建PIVOT查询并在查询中传递列名。如下......

DECLARE @sql NVARCHAR(MAX);

SET @sql = N'SELECT * FROM 
            (
            SELECT ID, [Key], Value
            FROM Test_Table_P
            WHERE ID = @ID)Q
              PIVOT (MAX(Value)
                     FOR [Key]
                     IN (' + @Cols + N')
                    )p'

构建查询后,您需要使用系统存储过程sp_executesql执行它。并且由于sp_executesql具有自己的作用域,并且声明的任何变量对sp_executesql都不可见,因此您需要将@ID作为其变量传递给sp_executesql。

EXECUTE sp_executesql @sql
                      ,N'@ID INT'
                      ,@ID

结果集

╔════╦═══════╦════════╦══════════╗
║ ID ║ Color ║ Access ║ LastCalc ║
╠════╬═══════╬════════╬══════════╣
║  1 ║    13 ║ H      ║ 17.06    ║
╚════╩═══════╩════════╩══════════╝