SQL 中的 UNPIVOT

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]
Unpivot Example 2

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])
Case and Cross Join for Unpivot table columns 4

上面针对数据透视列的代码的简化版本是

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。

Unpivot 5

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]
Alternative to Unpivot 6