这是我承诺的解决方案:
编辑:我修改了答案以回答 OP 提出的其他问题。
需要注意的几点:
- STUFF 函数:用于将 XML 字符串转换为常规字符串(并删除第一个逗号)
- Group By(我从 OMG Ponies 偷来的):您需要这样做以确保您没有任何重复的日期
- 在运行之前确保表格中没有太多的日期。列过多可能是个问题
- NVARCHAR:我使用它而不是 VARCHAR 作为 @sql 变量,因为 sp_ExecuteSQL 需要它。
- CONVERT(VARCHAR, DateColumn, 101):我这样做是因为除非您将日期转换为字符串,否则这是行不通的。 101 结果:mm/dd/yyyy,但你可以使用任何你需要的东西(确保它在这个脚本中使用的 2 次匹配)
- 为了使这适用于多列,您必须首先使用 UNPIVOT 并将所有列转换为相同的数据类型(代码下方有更多信息)
- 重要的是要注意,为了连接字符串,它们必须是相同的数据类型、相同的大小(在我的例子中,它们都是 NVARCHAR(MAX))
阅读this page 了解有关将日期转换为字符串的更多信息。
话虽如此,代码如下:
-- table with multiple columns
CREATE TABLE #TBL (
NameColumn VARCHAR(10),
PriorityColumn INT,
AnotherColumn FLOAT,
DateColumn DATETIME
)
-- Insert the test data
INSERT INTO #TBL VALUES ('a', 1, 7.2, '1/1/2000')
INSERT INTO #TBL VALUES ('a', 2, 8.9, '1/2/2000')
INSERT INTO #TBL VALUES ('a', 2, 53.2, '1/3/2000')
INSERT INTO #TBL VALUES ('a', 3, 9.12, '1/4/2000')
INSERT INTO #TBL VALUES ('b', 2, 1.26, '1/1/2001')
DECLARE
@sql NVARCHAR(max),
@dates NVARCHAR(max)
-- I separated this to make the code easier to read
SET @dates = STUFF(
(
SELECT N',[' + CONVERT(VARCHAR, DateColumn, 101) + ']' AS [text()]
FROM #TBL
GROUP BY DateColumn
ORDER BY DateColumn
FOR XML PATH('')
), 1, 1, N''
)
-- I will break this part of the code up below
SET @sql = N'SELECT
*
FROM (
SELECT
ColumnName,
ColumnValue,
CONVERT(VARCHAR, DateColumn, 101) AS DateString
FROM (
SELECT
CAST(NameColumn AS VARCHAR(100)) AS NameColumn,
CAST(PriorityColumn AS VARCHAR(100)) AS PriorityColumn,
CAST(AnotherColumn AS VARCHAR(100)) AS AnotherColumn,
DateColumn
FROM #TBL
) P
UNPIVOT (
ColumnValue
FOR ColumnName IN (NameColumn, PriorityColumn, AnotherColumn)
) UNPIV
) P2
PIVOT (
MAX(ColumnValue)
FOR DateString IN (' + @dates + N')
) PIV'
EXECUTE dbo.sp_ExecuteSQL @sql
DROP TABLE #TBL
让我们稍微了解一下
-- I first do an UNPIVOT on all of the columns I want to pivot on, at the same time, converting them to the same datatype
SELECT
ColumnName,
ColumnValue,
CONVERT(VARCHAR, DateColumn, 101) AS DateString
FROM (
SELECT
CAST(NameColumn AS VARCHAR(100)) AS NameColumn,
CAST(PriorityColumn AS VARCHAR(100)) AS PriorityColumn,
CAST(AnotherColumn AS VARCHAR(100)) AS AnotherColumn,
DateColumn
FROM #TBL
) P
UNPIVOT (
ColumnValue
FOR ColumnName IN (NameColumn, PriorityColumn, AnotherColumn)
) UNPIV
执行此操作后,数据将如下所示:
ColumnName ColumnValue DateString
----------------------------------
NameColumn a 01/01/2000
PriorityColumn 1 01/01/2000
AnotherColumn 7.2 01/01/2000
NameColumn a 01/02/2000
PriorityColumn 2 01/02/2000
AnotherColumn 8.9 01/02/2000
NameColumn a 01/03/2000
PriorityColumn 2 01/03/2000
AnotherColumn 53.2 01/03/2000
NameColumn a 01/04/2000
PriorityColumn 3 01/04/2000
AnotherColumn 9.12 01/04/2000
NameColumn b 01/01/2001
PriorityColumn 2 01/01/2001
AnotherColumn 1.26 01/01/2001
然后我们可以像这样使用 PIVOT 来获取我们需要的所有列:
PIVOT (
MAX(ColumnValue)
FOR DateString IN (' + @dates + N')
) PIV