没有找到合适的产品?
联系客服协助选型:023-68661681
提供3000多款全球软件/控件产品
针对软件研发的各个阶段提供专业培训与技术咨询
根据客户需求提供定制化的软件开发服务
全球知名设计软件,显著提升设计质量
打造以经营为中心,实现生产过程透明化管理
帮助企业合理产能分配,提高资源利用率
快速打造数字化生产线,实现全流程追溯
生产过程精准追溯,满足企业合规要求
以六西格玛为理论基础,实现产品质量全数字化管理
通过大屏电子看板,实现车间透明化管理
对设备进行全生命周期管理,提高设备综合利用率
实现设备数据的实时采集与监控
利用数字化技术提升油气勘探的效率和成功率
钻井计划优化、实时监控和风险评估
提供业务洞察与决策支持实现数据驱动决策
原创|使用教程|编辑:龚雪|2013-12-13 09:29:10.000|阅读 384 次
概述:UNPIVOT的确是在执行将列转化为行的任务时比较常用的方法,其优势也比较突出。本文将会介绍包括UNPIVOT在内的多种方法,而其中有比UNPIVOT更有优势的VALUES结构。
# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>
使用dynamic SQL可以在以下情况里对所有的表创建一个通用查询:在primary key里没有包含到列,但是有可兼容的数据类型存在时。
DECLARE@table_name SYSNAME
SELECT@table_name ='dbo.Players'
DECLARE@SQL NVARCHAR(MAX)
SELECT@SQL ='
SELECT *
FROM '+ @table_name +'
UNPIVOT (
value FOR code IN (
'+ STUFF((
SELECT', ['+ c.name+']'
FROMsys.columns cWITH(NOLOCK)
LEFTJOIN(
SELECTi.[object_id], i.column_id
FROMsys.index_columns iWITH(NOLOCK)
WHEREi.index_id = 1
) iONc.[object_id] = i.[object_id]ANDc.column_id = i.column_id
WHEREc.[object_id] = OBJECT_ID(@table_name)
ANDi.[object_id]ISNULL
FORXML PATH(''), TYPE).value('.','NVARCHAR(MAX)'), 1, 2,'') +'
)
) unpiv'
PRINT @SQL
EXECsys.sp_executesql @SQL
其结果为:
SELECT*
FROM<table_name>
UNPIVOT (
valueFORcodeIN(<unpivot_column>)
) unpiv
这个方法在速度上会比较慢一些,是因为UNPIVOT的自动生成查询需要从系统里进行额外的读取以及通过XML trick进行“行”的串联。
一个更聪明的办法来执行 dynamic UNPIVOT,是通过对XML做一个小窍门:
SELECT
p.PlayerID
, GameCount = t.c.value('.','INT')
, GameType = t.c.value('local-name(.)','VARCHAR(10)')
FROM(
SELECT
PlayerID
, [XML] = (
SELECTWin, Defeat, StandOff
FORXML RAW('f'), TYPE
)
FROMdbo.Players
) p
CROSSAPPLY p.[XML].nodes('f/@*') t(c)
按照以上的查询, SQL Server会对每一个行都生成一个XML:
<f Column1="Value1" Column2="Value2" Column3="Value3" ... />
接下来就是属性的名称和值被解析。大多数情况下,XML的使用会导致一个更慢的执行计划:

我们来对比一下通过执行 Compare Selected Results指令的结果:

我们可以看到,在执行查询的速度上,UNPIVOT和VALUES没有太明显的区别。当然,这只是针对简单的将列转化为行的任务而言。
现在我们用UNPIVOT语句再来做另外一个实验:
SELECT
PlayerID
, GameType = (
SELECTTOP1 GameType
FROMdbo.Players
UNPIVOT (
GameCountFORGameTypeIN(
Win, Defeat, StandOff
)
) unpvt
WHEREPlayerID = p.PlayerID
ORDERBYGameCountDESC
)
FROMdbo.Players p
这次的执行计划的瓶颈是对多重数据的读取和排序:

要解决这个瓶颈其实是相当的简单,我们可以使用来自外部查询的列的模块就能避免多重数据读取的问题:
SELECT
p.PlayerID
, GameType = (
SELECTTOP1 GameType
FROM(SELECTt = 1) t
UNPIVOT (
GameCountFORGameTypeIN(
Win, Defeat, StandOff
)
) unpvt
ORDERBYGameCountDESC
)
FROMdbo.Players p
这样一来读取多重的数据就被避免了,但是另外一个最消耗资源的操作——排序,仍然存在:

接下来就需要VALUES语句来发挥其作用了:
SELECT
t.PlayerID
, GameType = (
SELECTTOP1 GameType
FROM(
VALUES
(Win, 'Win')
, (Defeat, 'Defeat')
, (StandOff,'StandOff')
) t (GameCount, GameType)
ORDERBYGameCountDESC
)
FROMdbo.Players t
现在就如我们所预期的那样,执行计划被简化了,但是排序依然存在:

让我们尝试使用aggregation功能来消除掉排序:
SELECT
t.PlayerID
, GameType = (
SELECTTOP1 GameType
FROM(
VALUES
(Win, 'Win')
, (Defeat, 'Defeat')
, (StandOff,'StandOff')
) t (GameCount, GameType)
WHEREGameCount = (
SELECTMAX(Value)
FROM(
VALUES(Win), (Defeat), (StandOff)
) t(Value)
)
)
FROMdbo.Players t
现在,执行计划就如下图所示了:

结论:当我们需要在SQL SERVER里执行一个简单的将列转化为行的任务时,比较好的选择是使用 UNPIVOT或者VALUES结构。如果转换后的数据行是用作聚合或排序时,则最好使用VALUES结构,因为它能生成一个更有效率的执行计划。
>>点此免费下载试用dbForge Studio for SQL Server
本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@fc6vip.cn




本文将带大家学习如何在Kendo UI for Angular 网格组件中使用Angular的httpResource API,欢迎下载最新版组件体验!
本文主要介绍DevExpress WPF Grid控件如何将数据绑定虚拟数据源,欢迎下载最新版组件体验!
本教程主要为大家介绍DevExpress WinForms数据网格控件中的过滤器行功能,欢迎下载最新版组件体验!
本文主要介绍了Tool Call Confirmation API层和DevExpress Blazor AI Chat组件的相关可自定义接口,欢迎下载最新版体验!
相关产品
dbForge Studio for SQL Server是用于SQL Server的终极管理工具。
最新文章 MORE
金喜正规买球相关的文章 MORE
服务电话
重庆/ 023-68661681
华东/ 13452821722
华南/ 18100878085
华北/ 17347785263
客户支持
技术支持咨询服务
服务热线:400-700-1020
邮箱:sales@fc6vip.cn
关注我们
地址 : 重庆市九龙坡区火炬大道69号6幢
金喜正规买球