pivot unpivot

In this article, we’ll walk-through the SQL Pivot and SQL Unpivot operators and how they can be useful to transpose SQL Server data. Also, we’ll discuss both static and dynamic ways to use PIVOT and UNPIVOT relational operators that can be used to transform aggregated distinct values as column(s) in the result-set by specifying all the column values in the PIVOT IN clause.

在本文中,我们将逐步介绍SQL Pivot和SQL Unpivot运算符,以及它们如何对转置SQL Server数据有用。 此外,我们还将讨论使用PIVOT和UNPIVOT关系运算符的静态和动态方式,这些运算符可通过在PIVOT IN子句中指定所有列值来将聚合的不同值转换为结果集中的列。

SQL Server枢轴介绍 (SQL Server pivot Introduction)

There are several ways to transpose a dataset from rows to columns and columns to rows. SQL Pivot is one of the techniques that allows transposing of rows to columns and performs possible aggregations along the way. SQL PIVOT and SQL UNPIVOT relational operators transpose a table-valued two-dimensional data into another form of data. SQL PIVOT transposes a table-valued expression from a unique set of values from one column into multiple columns in the output and performs aggregations. SQL UNPIVOT performs the opposite operation of SQL PIVOT by transforming the columns of a table-valued expression into column values.

有几种方法可以将数据集从行到列以及从列到行进行转置。 SQL Pivot是一种允许将行转置为列并在此过程中执行可能的聚合的技术之一。 SQL PIVOT和SQL UNPIVOT关系运算符将表值的二维数据转换为另一种数据形式。 SQL PIVOT将来自一组唯一值的表值表达式转置为输出中的多个列,并执行聚合。 SQL UNPIVOT通过将表值表达式的列转换为列值来执行SQL PIVOT的相反操作。

In most cases, the static pivoting technique suffices the business requirement. For example, the monthly sales forecast, yearly sales split, quarterly sales aggregation, etc, where the IN clause columns remain static. In some other instances, we need granular details and the table-value expression is more dynamic in nature and all the time new set of the expression are included in the table then dynamic PIVOT would be the best choice.

在大多数情况下,静态旋转技术足以满足业务需求。 例如,月度销售预测,年度销售拆分,季度销售汇总等,其中IN子句列保持不变。 在其他一些情况下,我们需要细粒度的细节,并且表值表达式本质上是更动态的,并且表中始终包含新的表达式集,那么动态PIVOT将是最佳选择。

Note: In the above depiction, we can see that in the process of PIVOT, the column values are rotated from vertical to horizontal and UNPIVOTING is like rotating it from horizontal to vertical.

注意:在以上描述中,我们可以看到在PIVOT的过程中,列值从垂直旋转到水平,而UNPIVOTING就像从水平旋转到垂直。

Syntax

句法

SELECT <non-pivoted column>,

SELECT <非枢轴列>,

[pivot_column_1] AS <column alias>,

[pivot_column_1] AS <列别名>,

[pivot_column_2] AS <column alias>,

[pivot_column_2] AS <列别名>,

[pivot_column_n] AS <column alias>

[pivot_column_n] AS <列别名>

FROM

(

<SELECT QUERY>)

<选择查询>)

AS <Alias for temporary data set>

AS <临时数据集别名>

PIVOT

(

<Aggregate function>( Aggregate column)

<汇总功能>(“汇总”列)

FOR

对于

[<Pivot column will become column headers>]

[<枢轴列将成为列标题>]

IN ( [pivot_column_1], [pivot_column_2],

IN([pivot_column_1],[pivot_column_2],

… [pivot_column_n] )

…[pivot_column_n])

) AS <Pivot table alias>

)AS <数据透视表别名>

< ORDER BY clause>;

<ORDER BY子句>;

SQL Pivot入门 (Getting started with SQL Pivot)

We’re going to start with pivoting and un-pivoting the data. By now you understand what PIVOT and UNPIVOT operators are in SQL Server. In simple terms, it is just another way to describe the process of turning distinct row values into their own columns is known as Pivoting. And the process of turning columns into rows is known as an un-pivoting.

我们将从数据透视图和数据透视图开始。 到目前为止,您已经了解了SQL Server中的PIVOT和UNPIVOT运算符。 简单来说,这是描述将不同的行值转换为自己的列的过程的另一种方式,称为“透视”。 将列变成行的过程称为固定。

示例1 :如何执行SQL Pivot操作 (Example 1: How to perform a SQL Pivot operation)

Let’s picture the sample dataset derived from the AdventureWorks2014 database. In this case, you just got a simple dataset with SalesYear column along the one quantitative value TotalSales.

让我们对从AdventureWorks2014数据库派生的样本数据集进行图示。 在这种情况下,您只获得了一个带有SalesYear列的简单数据集以及一个定量值TotalSales。

Now, the dataset is ready for pivoting. You’ve got SalesYear in the first column, TotalSales in the second column. If you asked to transpose the data, you have to take every distinct year in the column and these columns become the header of the pivot columns. So, 2011 becomes the first column, 2012 becomes its own column and so on. The actual values from the next column Totalsales, they stick with the pivot column headers. Now, the pivoting table would look like below.

现在,数据集已准备好进行透视。 您在第一列中有SalesYear,在第二列中有TotalSales。 如果要求转置数据,则必须在该列中使用每个不同的年份,这些列将成为数据透视表列的标题。 因此,2011年成为第一列,2012年成为其自己的列,依此类推。 来自下一列Totalsales的实际值将保留在数据透视表列标题中。 现在,数据透视表如下所示。

SELECT * FROM
(
SELECT YEAR(SOH.OrderDate) as SalesYear,SOH.SubTotal as TotalSalesFROM sales.SalesOrderHeader SOHJOIN sales.SalesOrderDetail SOD ON SOH.SalesOrderId = SOD.SalesOrderId
) AS Sales
PIVOT (SUM(TotalSales)
FOR SalesYear IN ([2011],[2012],[2013],[2014]))
as PVT

The following image depicts the input data, Pivot syntax, SQL Pivot, and output results.

下图描述了输入数据,Pivot语法,SQL Pivot和输出结果。

示例2 :如何执行SQL Unpivot操作 (Example 2: How to perform a SQL Unpivot operation)

Let’s now look in the other direction, un-pivoting, which is as simple as going from horizontal to vertical. In this case, you’d take all of those distinct columns that are selected, and it would turn those column headers into their own rows. Pivoting is like rotating from vertical to horizontal. And un-pivoting is like rotating from horizontal to vertical.

现在,让我们从另一个方向来看,即不旋转,就像从水平到垂直一样简单。 在这种情况下,您将选择所有这些不同的列,并将这些列标题转换为自己的行。 旋转就像从垂直旋转到水平一样。 无枢轴旋转就像从水平旋转到垂直一样。

SELECT SalesYear, TotalSales
FROM
(SELECT *FROM(SELECT YEAR(SOH.OrderDate) AS SalesYear, SOH.SubTotal AS TotalSalesFROM sales.SalesOrderHeader SOHJOIN sales.SalesOrderDetail SOD ON SOH.SalesOrderId = SOD.SalesOrderId) AS Sales PIVOT(SUM(TotalSales) FOR SalesYear IN([2011], [2012], [2013], [2014])) AS PVT
) T UNPIVOT(TotalSales FOR SalesYear IN([2011], [2012], [2013], [2014])) AS upvt;

In the following example, the pivoted dataset is used to un-pivot the values. The key piece here is this was easy to do in getting transformed because we were able to create a pivot table as an intermediate step and then do the transformation using the unpivot operation.

在以下示例中,使用透视数据集取消透视值。 这里的关键是,转换很容易做到,因为我们能够创建一个数据透视表作为中间步骤,然后使用unpivot操作进行转换。

Note: SQL pivot operation results in transposing the aggregated result into column but whereas SQL unpivot is not an exact reversal of transposing columns into the segregated values of rows. The unpivot operator will not split the aggregated results.

注意:SQL透视操作会导致将聚合结果转置为列,但是SQL unpivot并不是将列转置为行的隔离值的确切逆转。 unpivot运算符不会拆分汇总结果。

示例3 :如何使用SQL Pivot操作获取季度销售额 (Example 3: How to get quarterly sales using SQL pivot operation)

Let’s see a few more examples to understand the pivoting concepts better. In this case, we’ll see how to get quarterly sales data aggregated based on the quarterly sales.

让我们再看一些示例,以更好地理解关键概念。 在这种情况下,我们将了解如何获取基于季度销售额的季度销售额数据。

Before we jump into the solution, it is always recommended to work on creating a dataset for the PIVOT operation.

在我们进入解决方案之前,始终建议为PIVOT操作创建数据集。

The following example gives the aggregated monthly sales spread over the sales year.

以下示例给出了跨销售年度的汇总每月销售。

SELECT YEAR(SOH.OrderDate) AS SalesYear, MONTH(SOH.OrderDate) AS SalesMonth, SUM(SOH.SubTotal) AS TotalSales
FROM sales.SalesOrderHeader SOHJOIN sales.SalesOrderDetail SOD ON SOH.SalesOrderId = SOD.SalesOrderId
GROUP BY YEAR(SOH.OrderDate), MONTH(SOH.OrderDate)
ORDER BY YEAR(SOH.OrderDate), MONTH(SOH.OrderDate);

The following output shows the base data

以下输出显示了基本数据

Once you’re ready with the base data, you can apply the PIVOT operator. In the following example, the IN clause accepts a non-numerical character that got generated based on the DATEPART value. The DATEPART value is concatenated with ‘Q’ and then the values are fed to IN clause of PIVOT operator.

一旦准备好基本数据,就可以应用PIVOT运算符。 在下面的示例中,IN子句接受基于DATEPART值生成的非数字字符。 DATEPART值与'Q'串联,然后将值馈送到PIVOT运算符的IN子句。

SELECT SalesYear, ISNULL([Q1], 0) AS Q1, ISNULL([Q2], 0) AS Q2, ISNULL([Q3], 0) AS Q3, ISNULL([Q4], 0) AS Q4, (ISNULL([Q1], 0) + ISNULL([Q2], 0) + ISNULL([Q3], 0) + ISNULL([Q4], 0)) SalesYTD
FROM
(SELECT YEAR(SOH.OrderDate) AS SalesYear, CAST('Q'+CAST(DATEPART(QUARTER, SOH.OrderDate) AS VARCHAR(1)) AS VARCHAR(2)) Quarters, SOH.SubTotal AS TotalSalesFROM sales.SalesOrderHeader SOHJOIN sales.SalesOrderDetail SOD ON SOH.SalesOrderId = SOD.SalesOrderId) AS Data PIVOT(SUM(TotalSales) FOR Quarters IN([Q1], [Q2], [Q3], [Q4])) AS pvt
ORDER BY SalesYear;

The following output is a quarterly split of the sales data

以下输出是销售数据的季度划分

示例4 :如何使用SQL透视操作获得月度销售额 (Example 4: How to get monthly sales using a SQL pivot operation)

Let us take a look into another example to see sales split data based on every month. In the following example, the IN clause values are generated as part of the DATEPART function. The DATEPART values are fed to IN clause of PIVOT operator.

让我们看看另一个示例,以查看每个月的销售拆分数据。 在下面的示例中,IN子句值作为DATEPART函数的一部分生成。 DATEPART值被馈送到PIVOT运算符的IN子句。

SELECT SalesYear, ISNULL([1], 0) AS Jan, ISNULL([2], 0) AS Feb, ISNULL([3], 0) AS Mar, ISNULL([4], 0) AS Apr, ISNULL([5], 0) AS May, ISNULL([6], 0) AS Jun, ISNULL([7], 0) AS Jul, ISNULL([8], 0) AS Aug, ISNULL([9], 0) AS Sep, ISNULL([10], 0) AS Oct, ISNULL([11], 0) AS Nov, ISNULL([12], 0) AS Dec, (ISNULL([1], 0) + ISNULL([2], 0) + ISNULL([3], 0) + ISNULL([4], 0) + ISNULL([4], 0) + ISNULL([5], 0) + ISNULL([6], 0) + ISNULL([7], 0) + ISNULL([8], 0) + ISNULL([9], 0) + ISNULL([10], 0) + ISNULL([11], 0) + ISNULL([12], 0)) SalesYTD
FROM
(SELECT YEAR(SOH.OrderDate) AS SalesYear, DATEPART(MONTH, SOH.OrderDate) Months,SOH.SubTotal AS TotalSalesFROM sales.SalesOrderHeader SOHJOIN sales.SalesOrderDetail SOD ON SOH.SalesOrderId = SOD.SalesOrderId) AS Data PIVOT(SUM(TotalSales) FOR Months IN([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12])) AS pvt;

The following output is a monthly split of the sales data

以下输出是销售数据的每月拆分

示例5 :如何使用动态SQL枢轴操作获取每月销售额 (Example 5: How to get monthly sales using dynamic SQL pivot operation)

Let us address the monthly split of sales data using dynamic pivoting. So far, we discussed static pivot operations. In order to convert a static pivot operation to dynamic, we’ve to remove the hardcoded values from the IN clause. First, get the distinct expression from the dataset and then prepare a string by concatenating all the expressions. In the following example, the @columnname is used to concatenate all the expression. The concatenated expression is fed to pivot IN clause. The rest is a simple conversion of static SQL into a dynamic SQL and call @DML using sp_executesql stored procedure.

让我们使用动态数据透视来解决销售数据的每月拆分。 到目前为止,我们讨论了静态枢轴操作。 为了将静态枢轴操作转换为动态操作,我们必须从IN子句中删除硬编码值。 首先,从数据集中获取不同的表达式,然后通过连接所有表达式来准备一个字符串。 在下面的示例中,@ columnname用于连接所有表达式。 串联的表达式被馈送到数据透视IN子句。 剩下的就是将静态SQL轻松转换为动态SQL,并使用sp_executesql存储过程调用@DML。

DECLARE @dml AS NVARCHAR(MAX)
DECLARE @ColumnName AS NVARCHAR(MAX)SELECT @ColumnName= ISNULL(@ColumnName + ',','') + QUOTENAME(Months)
FROM (SELECT DISTINCT  DATEPART(MONTH, SOH.OrderDate) MonthsFROM sales.SalesOrderHeader SOHJOIN sales.SalesOrderDetail SOD ON SOH.SalesOrderId = SOD.SalesOrderIdGROUP BY YEAR(SOH.OrderDate),
DATEPART(MONTH, SOH.OrderDate)) AS Months--Prepare the PIVOT query using the dynamic
SET @dml = N'SELECT SalesYear, ' +@ColumnName + ' FROM(SELECT YEAR(SOH.OrderDate) AS SalesYear, DATEPART(MONTH, SOH.OrderDate) Months,SUM(SOH.SubTotal) AS TotalSalesFROM sales.SalesOrderHeader SOHJOIN sales.SalesOrderDetail SOD ON SOH.SalesOrderId = SOD.SalesOrderIdGROUP BY YEAR(SOH.OrderDate),DATEPART(MONTH, SOH.OrderDate)) AS TPIVOT(SUM(TotalSales) FOR Months IN (' + @ColumnName + ')) AS PVTTable'
--Print @DynamicPivotQuery
--Execute the Dynamic Pivot Query
EXEC sp_executesql @dml

That’s all for now…

目前为止就这样了…

结语 (Wrapping Up)

Thus far, we’ve demonstrated the basic concepts and several examples of SQL PIVOT and SQL UNPIVOT.

到目前为止,我们已经演示了SQL PIVOT和SQL UNPIVOT的基本概念和几个示例。

The sample is based on the SQL Server adventureworks2014 database. You can give a try and test all the samples yourself. If you’ve any question, please feel free to comment below…

该示例基于SQL Server Adventureworks2014数据库。 您可以尝试自己测试所有样本。 如有任何疑问,请随时在下方评论...

翻译自: https://www.sqlshack.com/static-and-dynamic-sql-pivot-and-unpivot-relational-operator-overview/

pivot unpivot

pivot unpivot_静态和动态SQL Pivot和Unpivot关系运算符概述相关推荐

  1. 静态SQL和动态SQL

    引言 SQL 语言作为标准的查询语言,几乎被所有的数据库管理系统 (DBMS) 所支持,并成为国际标准.标准的 SQL 语言一般包括三类,即 DDL (Data Definition Language ...

  2. oracle 动态sql列转行_SQL Server中动态列转行

    http://www.cnblogs.com/gaizai/p/3753296.html 一.本文所涉及的内容(Contents) 三.实现代码(SQL Codes) (一) 首先我们先创建一个测试表 ...

  3. Mybatis系列全解(八):Mybatis的9大动态SQL标签你知道几个?提前致女神!

    封面:洛小汐 作者:潘潘 2021年,仰望天空,脚踏实地. 这算是春节后首篇 Mybatis 文了~ 跨了个年感觉写了有半个世纪 - 借着女神节 ヾ(◍°∇°◍)ノ゙ 提前祝男神女神们越靓越富越嗨森! ...

  4. java回顾:MyBatis参数、sql片段、动态sql、高级查询

    目录 一.MyBatis参数 SqlSessiong工具类 1.映射文件配置-入参 1.1 parameterType入参 1.2 单个入参,变量名任意定义: 1.3 多个入参,解决方案: 1.4 p ...

  5. Ms sql pivot unpivot

    Ms sql pivot unpivot --建表 create table dbo.orders ( orderid int not null primary key nonclustered,or ...

  6. oracle静态,oracle静态sql和动态sql

    Excute immediate 动态SQL语句 using 绑定参数列表 returning into 输出参数列表; 对这一语句作如下说明: 1) 动态SQL是指DDL和不确定的DML(即带参数的 ...

  7. 动态SQL与静态SQL

    SQL 语句从编译和运行的角度可以分为静态 SQL和 动态 SQL,所谓SQL的动态和静态,是指SQL语句在何时被编译和执行. 这两种 SQL 在使用方式.运行机制和性能表现等方面各有特点 : 静态 ...

  8. declare sql语句_SQL高级知识——动态SQL

    在介绍动态SQL前我们先看看什么是静态SQL 静态SQL 静态 SQL 语句一般用于嵌入式 SQL 应用中,在程序运行前,SQL 语句必须是确定的,例如 SQL 语句中涉及的列名和表名必须是存在的.静 ...

  9. SQL中的动态SQL

    在介绍动态SQL前我们先看看什么是静态SQL 静态SQL 静态 SQL 语句一般用于嵌入式 SQL 应用中,在程序运行前,SQL 语句必须是确定的,例如 SQL 语句中涉及的列名和表名必须是存在的.静 ...

最新文章

  1. java 将单词转换为_java – 将int列表转换为单词
  2. 1-5-20:球弹跳高度的计算
  3. linux桌面文件夹改图标,Linux 给桌面程序设置个性化图标
  4. 图马尔可夫网络:融合统计关系学习与图神经网络
  5. mfc中UpdateData的用法
  6. srt编辑的文件在linux显示乱码,解决看本地视频srt字幕乱码问题教程-srt文件
  7. 0x80070659系统策略禁止这个安装_教你如何将电脑C盘设置成禁止安装任何软件
  8. Python+sklearn使用朴素贝叶斯算法识别中文垃圾邮件
  9. Hi!怂程见证我开博。
  10. 多线程占用修改同一excel文件冲突_漫谈Excel报表移动化的逐级解决方案
  11. win7系统不能加入工作组计算机,技术员教你解决win7系统工作组计算机无法访问的修复办法...
  12. spfa slf优化
  13. 2021-0409梦笔记
  14. 版本管理工具git的使用总结
  15. c语言中find的作用,c语言find函数的用法详解
  16. android swf 播放器 源码,Android 9.0 flash播放器播放swf源码讲解
  17. MySql查询某个时间段内的数据
  18. 大一到研二我收藏了数百个网址,从中挑选了十五个最值得收藏的网址推荐给你
  19. XJOI 9552矩阵游戏(2级1段)
  20. 自定义注解+拦截器优化项目代码

热门文章

  1. vue生成带签名的apk
  2. How many ways?? - hdu2157(矩阵快速幂-模板)
  3. BZOJ1110 : [POI2007]砝码Odw
  4. spring mvc 下载文件链接
  5. cf486A Calculating Function
  6. 基于Emgu cv的图像拼接(转)
  7. Oracle数据库备份dmp文件,使用cmd命令导入导出步骤,以及忘记Oracle密码
  8. 【转】一劳永获的解决textbox 只能输入数字、汉字、字母等问题
  9. ES6——Generator 函数的语法
  10. LeetCode(637)——二叉树的层平均值(JavaScript)