SQL Server用Cross ApplyCross Join实现列转行

Posted 詩和遠方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL Server用Cross ApplyCross Join实现列转行相关的知识,希望对你有一定的参考价值。

今天介绍4种列转行(又称宽表转长表、逆透视等)写法。

数据准备

CREATE TABLE Sales([Year] INT,Q1 INT,Q2 INT,Q3 INT,Q4 INT);
GO
INSERT INTO Sales([Year],Q1,Q2,Q3,Q4)
    VALUES (2017,12,123,324,123)
          ,(2018,13,455,324,878)
          ,(2019,29,786,473,633);

SQL写法

UNION

最传统最通用写法

SELECT [Year],'Q1' AS [Quarter],Q1 AS Amount FROM Sales UNION ALL
SELECT [Year],'Q2' AS [Quarter],Q2 AS Amount FROM Sales UNION ALL
SELECT [Year],'Q3' AS [Quarter],Q3 AS Amount FROM Sales UNION ALL
SELECT [Year],'Q4' AS [Quarter],Q4 AS Amount FROM Sales; 
UNPIVOT

unpivot 的独特语法:

SELECT [Year],[Quarter],[Amount]
FROM Sales AS a
UNPIVOT(Amount FOR [Quarter] IN (Q1,Q2,Q3,Q4)) AS b;
CROSS JOIN

其实就是笛卡尔积,用CROSS JOIN是MSSQL的推荐写法,其它数据库若不支持此语法,可以将CROSS JOIN替换为逗号,或用Join On 1 = 1

SELECT a.[Year],b.[Quarter]
      ,CASE b.[Quarter] 
           WHEN 'Q1' THEN Q1
           WHEN 'Q2' THEN Q2
           WHEN 'Q3' THEN Q3
           WHEN 'Q4' THEN Q4
       END AS Amout
FROM Sales a
CROSS JOIN (VALUES ('Q1'),('Q2'),('Q3'),('Q4')) AS b([Quarter]);
CROSS APPLY

CROSS APPLY是个强大的操作符,也可以用来实现unpivot:

SELECT a.[Year], b.[Quarter],b.Amount
FROM Sales a
CROSS APPLY (SELECT 'Q1' AS [Quarter],a.Q1 AS Amount UNION ALL 
             SELECT 'Q2',a.Q2 UNION ALL 
             SELECT 'Q3',a.Q3 UNION ALL 
             SELECT 'Q4',a.Q4) AS b;
-- 或
SELECT a.[Year], b.[Quarter],b.Amount
FROM Sales a
CROSS APPLY (VALUES ('Q1',a.Q1)
                   ,('Q2',a.Q2)
                   ,('Q3',a.Q3)
                   ,('Q4',a.Q4)) AS b([Quarter],Amount);

总结与说明

  • 传统的Union写法需要扫描多次基表,效率最差
  • UNPIVOT写法最简洁,而且执行效率高,但语法有点晦涩,不是SQL的典型风格
  • CROSS JOIN与CROSS APPLY写法也只要扫描一次基表,可能执行效率比UNPIVOT差一点点,但好处是语法上更灵活

以上是关于SQL Server用Cross ApplyCross Join实现列转行的主要内容,如果未能解决你的问题,请参考以下文章

Hive 上的 CROSS APPLY SQL Server 查询

如何处理 CROSS APPLY [SQL Server] 中的空行

SQL Server outer apply 和 cross apply

SQL Server:CROSS JOIN 和 FULL OUTER JOIN 有啥区别?

SQL Server:仅使用一次 Join/Cross Apply 中的记录

在 SQL Server 2008 中使用 Unpivot 或 Cross Apply 规范化数据