关于UNPIVOT 操作符

关于UNPIVOT 操作符

 

UNPIVOT 操作符说明

简而言之,UNPIVOT操作符就是取得一个行的数据集合,然后把每一行都转换成多个行数据。为了更好地理解,请看下图:

UNPIVOT Operation

图1

从上图中,你能发现UNPOVOT操作符,取得了两行数据,每行包含三个Price值,然后将这些转化成6行数据,其中每个产品价格都是一个不同的行。

UNPIVOT 命令制定了两个不同的列类型。第一个类型是列中不被转换的。在例子中,ID、产品名字列是这样的列类型。第二种列类型就是那些被转换的。诸如ProductCode, Wholesale 和Retail 这三列。在我上面的例子中,那些没有被转换的列将被在每套列值集合中重复,而另外的那些列将被转换成行。

UNPIVOT 语法

下面就是 UNPIVOT 的语法:

SELECT [columns not unpivoted],
	 [unpivot_column],
       [value_column],
FROM
(<source query>)
AS <alias for the source data>
UNPIVOT ( [value_column] FOR [unpivot_column] IN ( <column_list> ) ) 
   AS <alias for unpivot>

Where:

    • [columns not unpivoted]: 不被转换的列的名字清单。
    • [unpivot_column]: 不转换的列的名称。
    • [value_column]: 确定一个列名称来代表不转换的列的数据。
    • <source query>: 源数据。
  •       <alias for the source data>: 为源数据转换后的表确定一个别名。
  •       <column_list>:  被转换的列的列名称。
  •      <alias for unpivot>: 为转换操作的整套生产,确定一个别名。

为了更好地理解我们看下面的例子:

简单的例子

USE tempdb;
GO
IF object_id('PhoneNumbers') IS NOT NULL DROP TABLE PhoneNumbers;
GO
CREATE TABLE PhoneNumbers (
	PersonID int, 
	HomePhone varchar(12),
	CellPhone varchar(12), 
	Workphone varchar(12), 
	FaxNumber varchar(12));

INSERT INTO PhoneNumbers VALUES 
	(1,Null,'444-555-2931',Null,Null),
	(2,'444-555-1950','444-555-2931',Null, Null),
	(3,'444-555-1950', Null,'444-555-1324','444-555-2310'),
	(4,'444-555-1950','444-555-2931','444-555-1324',
        '444-555-1987');

Listing 1: 创建并填充PhoneNumbers 数据

SELECT PersonID, PhoneType, PhoneNumber
FROM (
	SELECT PersonID, HomePhone, CellPhone, Workphone, FaxNumber
	FROM PhoneNumbers ) AS Src
	UNPIVOT (
		PhoneNumber FOR PhoneType IN 
		(HomePhone, CellPhone, WorkPhone, FaxNumber)) AS UNPVT;

Listing 2: 行列转换语法例子

执行上面代码后显示如下图:

unpivot

通过这个例子,我们发现执行结果中每行数据只包含一个单一的电话号码,同时注意到结果中在原表中有几个号码不为null则有几行数据,ID也就有几次。接下来我们进一步通过使用UNPIVOT来加深认识。

使用两个UNPIVOT操作符

第二个例子中,我将使用两个操作符来行转列来转换一套名字/值 的两列数据。具体如下:

unpivot1

 

在表 CustPref里面 我有四对名称和值。

我们将使用不同的UNPIVOT操作符来创建一个结果集,每一个PrefType的名字和值针对每个CustID 和CustName。并联使用操作符的作用是为了转换两组列。这样讲能表示为一个参数名称和值在一行里面。执行代码如下:

3http://www.cnblogs.com/wenBlog/

通过这个输出结果,能发现不同的type对应不同的值得列,并且要关联CustID。整个查询通过两个不同的UNPOVOT操作符同时使用了where 子句来合并输出结果(基于列名前五个字符相同的进行匹配),第一个行转列转换的是数据,第二个为类型,where限制了比较前五个字符,我能取得匹配的数据组。

动态UNPIVOT查询

代码如下:

USE tempdb;
GO
DECLARE @ColNames varchar(1000);
SET @ColNames = '';
-- Get PrefValue Columns
SELECT @ColNames=stuff((
    SELECT DISTINCT ',' + QUOTENAME(COLUMN_NAME)
    FROM INFORMATION_SCHEMA.COLUMNS p2
    WHERE TABLE_NAME = 'CustPref'
	  AND COLUMN_NAME like 'Pref_Type'
    FOR XML PATH(''), TYPE).value('.', 'varchar(max)')
            ,1,1,'')
-- Get PrefType Columns
DECLARE @ColValues varchar(1000);
SET @ColValues = '';
SELECT @ColValues=stuff((
    SELECT DISTINCT ',' + QUOTENAME(COLUMN_NAME)
    FROM INFORMATION_SCHEMA.COLUMNS p2
    WHERE TABLE_NAME = 'CustPref'
	  AND COLUMN_NAME like 'Pref_Data'
    FOR XML PATH(''), TYPE).value('.', 'varchar(max)')
            ,1,1,'')
-- Generate UNPIVOT Statement
DECLARE @CMD nvarchar(2000);
SET @CMD = 'SELECT CustId, CustName, PrefType, PrefValue FROM ' + 
           '(SELECT CustID, CustName, ' + @ColNames + ',' + @ColValues + 
		   ' FROM CustPref) AS Perf UNPIVOT (PrefValue FOR PrefValues IN (' +  
		   @ColValues + ')) AS UP1 UNPIVOT (PrefType FOR PrefTypes IN (' + 
		   @ColNames + ')) AS UP2 WHERE ' + 
		   'substring(PrefValues,5,1) = substring(PrefTypes,5,1);'
-- Print UNPIVOT Command
PRINT @CMD
-- Execute UNPIVOT Command
execute sp_executesql @CMD

结果是与上面的例子完全相同的。

为了完成和这个动态的SQL,我使用了INFORMATION_SCHEMA.COLUMNS视图。这个视图能帮我们设定两个变量@ColNames和@ColValues ,这就包含了用逗号区分的列名的字符串。这两个变量被用来构建动态的行转列查询。一旦我建立了动态的SQL就能,执行这个sp_executesql了。

这是一个简单的实例,但是相同的逻辑可以应用于更多的不同的组列的转换。

Summary

UNPIVOT操作符在2005 首次被引入,允许我们将多个name/value 列从不规范的表中创建到一个规范画的结果集中,并且一一对应于选定的列。通过使用这个操作符,我们能同时转换多个不同组的name/value 的成对的列。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/119738.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 基于单片机的空气质量检测系统设计_单片机有难度毕业设计

    基于单片机的空气质量检测系统设计_单片机有难度毕业设计实物链接:基于单片机的空气质量检测-实物设计软件安装:Keil:点击下载 Proteus:点击下载 AD:点击下载 Visio:点击下载设计简介:本设计是基于单片机的空气质量检测设计,主要实现以下功能:可实现通过SGP30测量二氧化碳及甲醛浓度,当超过设置的最大值时,进行报警及通风和净化空气处理 可实现通过MQ-4测量甲烷浓度,当超过设置的最大值时,进行报警及通风和净化空气处理 可实现通过GP2Y10测量5浓度,当超过设置的最大值时,进行报警及通风和净化空气处理 可实现通过

    2022年10月3日
    3
  • 读写锁属性[通俗易懂]

    读写锁属性[通俗易懂]本文转载自zfy3000《读写锁属性》通过读写锁,可以对受保护的共享资源进行并发读取和独占写入。读写锁是可以在读取或写入模式下锁定的单一实体。要修改资源,线程必须首先获取互斥写锁。必须释放所有读锁之后,才允许使用互斥写锁。有关Solaris线程所实现的读写锁,请参见相似的同步函数-读写锁。对数据库的访问可以使用读写锁进行同步。读写锁支持并发读取数据库记录,因为读操作

    2022年8月12日
    7
  • 联合国世界卫生组织(WHO)认为健康的包括哪些方面?_联合国世界卫生组织把健康定义为

    联合国世界卫生组织(WHO)认为健康的包括哪些方面?_联合国世界卫生组织把健康定义为联合国世界卫生组织(WHO)对健康的定义是,即“健康不仅是没有疾病,而且包括躯体健康、心理健康、社会适应良好和道德健康”。由此可知,健康不仅仅是指躯体健康,还包括心理、社会适应、道德品质相互依存、相

    2022年8月1日
    6
  • html语言添加下划线,HTML页面中怎么文本添加下划线?[通俗易懂]

    html语言添加下划线,HTML页面中怎么文本添加下划线?[通俗易懂]怎么在HTML页面中给文本添加下划线?下面本篇文章就来给大家介绍一下HTML、CSS给文本添加下划线的方法,希望对大家有所帮助。HTML添加下划线在HTML中可以使用标签定义下划线文本,即为文本添加下划线。下划线标签告诉浏览器把加入到u标签的文本加下划线样式呈现显示给浏览者。对于所有浏览器来说,这意味着要把这段文字加下划线样式方式呈现给大家显示。语法:我被加下划线了说明:标签定义与常规文本风格不…

    2022年6月3日
    39
  • 钉钉自定义机器人发送消息到钉钉群[通俗易懂]

    钉钉自定义机器人发送消息到钉钉群[通俗易懂]1、新建机器人2、生成密钥packagecom.epmet.commons.tools.utils;/***描述一下**@authorxxxx*@date2020/6/2417:42*/importjavax.crypto.Mac;importjavax.crypto.spec.SecretKeySpec;importorg.apache.commons.codec.binary.Base64;importjava.net.URLEncod

    2022年5月13日
    52
  • kafka主要用来做什么_kafka概念

    kafka主要用来做什么_kafka概念Kafka最初由LinkedIn公司开发的,并于2010年贡献给了Apache基金会,之后成为Apache顶级项目。目前Kafka已经定位为一个分布式流式处理平台,它以高吞吐、可持久化、可水平扩展、支持流数据处理等多种特性而被广泛使用。目前越来越多的开源分布式处理系统如Cloudera、Storm、Spark、Flink等都支持与Kafka集成。Kafka之所以受到越来越多的青睐,与它所“扮演”的三大角色是分不开的:消息系统:Kafka和传统的消息系统(也称作消息中

    2022年9月25日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号