我怀疑使用 可能有一个非常好的方法PIVOT
,但我不太了解它可以肯定地说。我在这里提供的工作。为了更好地格式化并提供评论,我已将其拆分为多个块:
首先让我们捕获示例数据
-- Sample data
DECLARE @x3 xml
SET @x3 = '
<root>
<row>
<column>row 1 col 1</column>
<column>row 1 col 2</column>
<column>row 1 col 3</column>
</row>
<row>
<column>row 2 col 1</column>
<column>row 2 col 2</column>
<column>row 2 col 3</column>
</row>
<row>
<column>row 3 col 1</column>
<column>row 3 col 2</column>
<column>row 3 col 3</column>
</row>
</root>
'
DECLARE @x xml
SET @x = @x3
-- @x is now our input
现在实际的转置代码:
建立矩阵的大小:
WITH Size(Size) AS
(
SELECT CAST(SQRT(COUNT(*)) AS int)
FROM @x.nodes('/root/row/column') T(C)
)
切碎数据,用于ROW_NUMBER
捕获索引(-1
使其从零开始),并在索引上使用模数和整数除法来计算新的行号和列号:
,Flattened(NewRow, NewCol, Value) AS
(
SELECT
-- i/@size as old_r, i % @size as old_c,
i % (SELECT TOP 1 Size FROM Size) AS NewRow,
i / (SELECT TOP 1 Size FROM Size) AS NewCol,
Value
FROM (
SELECT
(ROW_NUMBER() OVER (ORDER BY C)) - 1 AS i,
C.value('.', 'nvarchar(100)') AS Value
FROM @x.nodes('/root/row/column') T(C)
) ShreddedInput
)
有了这个 CTE FlattenedInput
,我们现在需要做的就是FOR XML
正确选择选项和查询结构,然后我们就完成了:
SELECT
(
SELECT Value 'column'
FROM
Flattened t_inner
WHERE
t_inner.NewRow = t_outer.NewRow
FOR XML PATH(''), TYPE
) row
FROM
Flattened t_outer
GROUP BY NewRow
FOR XML PATH(''), ROOT('root')
样本输出:
<root>
<row>
<column>row 1 col 1</column>
<column>row 2 col 1</column>
<column>row 3 col 1</column>
</row>
<row>
<column>row 1 col 2</column>
<column>row 2 col 2</column>
<column>row 3 col 2</column>
</row>
<row>
<column>row 1 col 3</column>
<column>row 2 col 3</column>
<column>row 3 col 3</column>
</row>
</root>
适用于任何大小的“方形”数据。请注意缺乏健全性检查/错误处理。