关于UNPIVOT 操作符
UNPIVOT 操作符说明
简而言之,UNPIVOT操作符就是取得一个行的数据集合,然后把每一行都转换成多个行数据。为了更好地理解,请看下图:
图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: 行列转换语法例子
执行上面代码后显示如下图:
通过这个例子,我们发现执行结果中每行数据只包含一个单一的电话号码,同时注意到结果中在原表中有几个号码不为null则有几行数据,ID也就有几次。接下来我们进一步通过使用UNPIVOT来加深认识。
使用两个UNPIVOT操作符
第二个例子中,我将使用两个操作符来行转列来转换一套名字/值 的两列数据。具体如下:
在表 CustPref里面 我有四对名称和值。
我们将使用不同的UNPIVOT操作符来创建一个结果集,每一个PrefType的名字和值针对每个CustID 和CustName。并联使用操作符的作用是为了转换两组列。这样讲能表示为一个参数名称和值在一行里面。执行代码如下:
http://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 的成对的列。
关于UNPIVOT 操作符的更多相关文章
- SQL Server的事务处理与高级查询
6.高级查询与脚本 6.1子查询 位于SELECT查询中的SELECT查询. 6.11 标量表达式 select id,val,val-(select avg(val) from tbltest) f ...
- KingbaseES 的行列转换
目录 背景 行转列 数据准备 分组聚合函数+CASE 根据压缩数据的格式,横向展开数据列选取不同方式 crosstab函数 PIVOT 操作符 PIVOT 操作符的限制 工具 ksql 的元命令 \c ...
- Oracle 的基本操作符
!= 不等于 select empno,ename,job from scott.emp where job!='manager' ^= 不等于 select empno,ename,job from ...
- Pivot 和 Unpivot
在TSQL中,使用Pivot和Unpivot运算符将一个关系表转换成另外一个关系表,两个命令实现的操作是“相反”的,但是,pivot之后,不能通过unpivot将数据还原.这两个运算符的操作数比较复杂 ...
- javascript中的操作符详解1
好久没有写点什么了,根据博主的技术,仍然写一点javascript新手入门文章,接下来我们一起来探讨javascript的操作符. 一.前言 javascript中有许多操作符,但是许多初学者并不理解 ...
- c# 基础 object ,new操作符,类型转换
参考页面: http://www.yuanjiaocheng.net/webapi/config-webapi.html http://www.yuanjiaocheng.net/webapi/web ...
- oracle操作符
Oracle中算术操作符(+)(-)(*)(/) 值得注意的是:/ 在oracle中就相当于显示中的除法 5/2 = 2.5 比较操作符: 其中等号可以换成其他运算符:(后面为该操作符的单条件查询样例 ...
- C# 本质论 第三章 操作符和控制流
操作符通常分为3大类:一元操作符(正.负).二元操作符(加.减.乘.除.取余)和三元操作符( condition?consequence:alternative(consequence和alterna ...
- SQL优化技术分析-1:操作符优化
1.IN 操作符 用IN写出来的SQL的优点是比较容易写及清晰易懂,这比较适合现代软件开发的风格.但是用IN的SQL 性能总是比较低的,从Oracle执行的步骤来分析用IN的SQL与不用IN的SQL有 ...
随机推荐
- jquery.tagthis和jquery.autocomplete一起实现标签
目的 jquery.tagthis:http://www.dangribbin.co/jquery-tag-this/demo/ 使用tagthis控件实现标签的输入提醒功能,每个标签具有id和tex ...
- 优秀的技术Leader
在一个"情怀"已经泛滥的年代里,任何拿着"情怀"出来说事的人都不太受待见.犀利者会吐槽:"我早已看穿了一切". 但你是否想过,如果这世界所有 ...
- [moka同学笔记]Yii2 自定义class、自定义全局函数(摘录)
1.在app\components下新建MyComponent.PHP namespace app\components; use Yii; use yii\base\Component; use y ...
- 转载java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.spinner/com.example.spinner.MainActivity}: java.lang.NullPointerException
今天学习Android开发突然遇到了这个问题,查阅了很多资料,并且对集中原因进行了分析. 错误信息字符串:java.lang.RuntimeException: Unable to start act ...
- spring入门(二)【加载properties文件】
在开发过程当中需要用到配置信息,这些信息不能进行硬编码,这时配置文件是一个比较好的方式,java提供了properties格式的文件,以键值对的方式保存信息,在读取的时候通过键获得键对应的值,spri ...
- Android总结篇系列:Android Intent
Intent在Android中的重要性不言而喻.本文主要总结下Intent使用过程中需要注意的一些问题. 1.隐式Intent AndroidManifest.xml声明时<intent-fil ...
- FilterDispatcher已被标注为过时解决办法 >>> FilterDispatcher <<< is deprecated!
一些struts2的教程都是比较早的,当我们基于较新版本的struts2来实现代码的时候,往往会出现一些问题.比如这个警告:FilterDispatcher isdeprecated! 在web.xm ...
- 定时任务服务 CronService使用说明
CronServiceInstaller.exe 部署安装程序 1.在打开该程序前务必设置为管理员运行 2.点击注册服务 3.检查服务是否开启,点击 services.msc, 打开系统服务列表 4 ...
- padding下中英文左右两端对齐
<!DOCTYPE html> <html> <head> <meta charset='UTF-8'> <title>helo</t ...
- html和css的编码规范
HTML和CSS编码规范内容 一.HTML规范 二.CSS规范 三.注意事项: 四.常用的命名规则 五.CSS样式表文件命名 六.文件命名规则 一.HTML规范: 1.代码规范 页面的第一行添加标准模 ...