转置未知数量的列

时间:2015-05-26 14:05:07

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

我正在寻找一种使用T-SQL将行转换为列的有效方法。

这是样本数据:

+----+--------------+----------------+
| ID |  ColumnName  |     Value      |
+----+--------------+----------------+
|  1 | FirstName    | Name 1         |
|  2 | FirstName    | Name 2         |
|  3 | FirstName    | Name 3         |
|  4 | FirstName    | Name 4         |
|  1 | LastName     | LastName 1     |
|  2 | LastName     | LastName 2     |
|  3 | LastName     | LastName 3     |
|  4 | LastName     | LastName 4     |
|  1 | MobileNumber | MobileNumber 1 |
|  2 | MobileNumber | MobileNumber 2 |
|  3 | MobileNumber | MobileNumber 3 |
|  4 | MobileNumber | MobileNumber 4 |
+----+--------------+----------------+

这是预期的结果:

+----+-----------+------------+----------------+
| ID | FirstName |  LastName  |  MobileNumber  |
+----+-----------+------------+----------------+
|  1 | Name 1    | LastName 1 | MobileNumber 1 |
|  2 | Name 2    | LastName 2 | MobileNumber 2 |
|  3 | Name 3    | LastName 3 | MobileNumber 3 |
|  4 | Name 4    | LastName 4 | MobileNumber 4 |
+----+-----------+------------+----------------+

如何构建查询?

我尝试了以下链接(以及更多),但我无法达到预期效果:

Efficiently convert rows to columns in sql server

Simple way to transpose columns and rows in Sql?

2 个答案:

答案 0 :(得分:2)

尝试使用像这样的动态轴(这是假设你的问题中的ID是一个错误,实际上应该是1,2,3,4,1,2,3,4 ......等)。我已经包含了一个"数据清理"避免任何SQL注入回归:

Declare @SQL nvarchar(max)
Declare @columns nvarchar(max)

Select @columns = (Select Distinct Quotename(Columnname) + ',' from table for xml path(''))
Set @columns = Left(@columns, Len(@columns) - 1)

Set @SQL = 'Select ID, ' + @columns + '
from
(Select ID, Value, Columnname
from table) as src
PIVOT
(Max(Value) FOR Columnname in (' + @columns + ')) as pvt'

exec sp_executesql @SQL

SQL小提琴:http://www.sqlfiddle.com/#!3/7a79d2/5

答案 1 :(得分:1)

欢迎来到Dynamic Pivots!您可以使用此类查询来提取动态的列集:

DECLARE @SQL NVARCHAR(MAX)
DECLARE @VALS NVARCHAR(500)

SELECT DISTINCT [COLUMNNAME] AS VALS
INTO #VALS
FROM TABLE1

SELECT @VALS = COALESCE(@VALS+', ','') + '[' + VALS + ']' FROM #VALS

SET @SQL = '
SELECT ID, '+@VALS+'
FROM TABLE1
PIVOT(MIN([VALUE]) FOR [COLUMNNAME] IN ('+@VALS+')) PIV'
PRINT @SQL
EXEC(@SQL)

这是一个SQL小提琴:http://sqlfiddle.com/#!6/48bc8/1

请注意我实际上是如何更改您的示例数据的,因为我认为您错误地构造了它。请参阅ID列以查看差异。如果这代表您的实际数据,我会感到非常惊讶。