SQL Server 的 Unpivot 是最有用的运算符之一,用于将列名转换为行值。或者说,将数据透视表旋转为常规表。让我们通过一个示例,看看如何使用 Unpivot 将列名转换为行值。
下面的源截图显示了我们表中的数据。我们将使用这些数据透视数据,将列名(2011、2012、2013 和 2013)转换为行值。

SQL UNPIVOT 示例
在此示例中,我们将使用此内置运算符将列名(2011、12、13 和 2014)转换为行值。我们必须将其与 IN 运算符一起使用。在此 SQL 示例中,“产品名称”列的值将保持不变。但是,“订单数量”会根据“订单年份”重新排列。
SELECT [Product Name]
,[Order Year]
,[Order Quantity]
FROM [SQLUnPivot Source]
UNPIVOT (
[Order Quantity] FOR [Order Year]
IN ([2011],[2012],[2013],[2014])
) AS [UNPIVOT TABLE]

SQL Server UNPIVOT 替代方案
如果面试官希望测试您的编码技能,那么您可以期待实现 Unpivot 功能的替代方法。
使用 Cross Apply Values 作为替代方案
在此示例中,我们使用 Cross Apply 来对上述指定的 数据透视表进行 unpivot 操作。
SELECT Original.[Product Name]
,Unpivoted.[Order Year]
,Unpivoted.[Order Quantity]
FROM [SQLUnPivot Source] AS Original
CROSS APPLY
(
VALUES
([2011], '2011')
,([2012], '2012')
,([2013], '2013')
,([2014], '2014')
) Unpivoted ([Order Year], [Order Quantity] )

Unpivot 替代方案:Case 语句与 Cross Join
将 Case 语句与 Cross Join 结合使用,以实现此 unpivot 表列功能。
SELECT
Original.[Product Name],
Unpivoted.[Order Year],
[Order Quantity] =
CASE Unpivoted.[Order Year]
WHEN '2011' THEN Original.[2011]
WHEN '2012' THEN Original.[2012]
WHEN '2013' THEN Original.[2013]
WHEN '2014' THEN Original.[2014]
END
FROM (
SELECT [Product Name],[2011],[2012],[2013],[2014]
FROM [SQLUnPivot Source]
) AS Original
CROSS JOIN
(
SELECT '2011' UNION ALL
SELECT '2012' UNION ALL
SELECT '2013' UNION ALL
SELECT '2014'
) Unpivoted ([Order Year])

上面针对数据透视列的代码的简化版本是
SELECT
Original.[Product Name],
Unpivoted.[Order Year],
[Order Quantity] =
CASE Unpivoted.[Order Year]
WHEN '2011' THEN Original.[2011]
WHEN '2012' THEN Original.[2012]
WHEN '2013' THEN Original.[2013]
WHEN '2014' THEN Original.[2014]
END
FROM (
SELECT [Product Name],[2011],[2012],[2013],[2014]
FROM [SQLUnPivot Source]
) AS Original
CROSS JOIN
(
VALUES ('2011'), ('2012'), ('2013'), ('2014')
) Unpivoted ([Order Year])
使用 Values 关键字,而不是使用旧的传统 Union All。

Union All Unpivot 替代方案
在此示例中,我们使用 Union All 作为替代方案。这可能不是理想的方法,但您会明白要点。
SELECT [Product Name],
[Order Quantity] = [2011],
[Order Year] = '2011'
FROM [SQLUnPivot Source]
UNION ALL
SELECT [Product Name], [2012], '2012'
FROM [SQLUnPivot Source]
UNION ALL
SELECT [Product Name], [2013], '2013'
FROM [SQLUnPivot Source]
UNION ALL
SELECT [Product Name], [2014], '2014'
FROM [SQLUnPivot Source]
ORDER BY [Product Name]
