T-SQL——透视PIVOT动态获取待扩展元素集
0.背景说明
在T-SQL——数据透视和逆透视文中介绍了透视和逆透视
使用PIVOT对结果集进行数据透视
SELECT FROM Table PIVOT(任意聚合函数(聚合字段) FOR 待扩展字段名 IN (待扩展元素集)) AS T
其中的 待扩展元素集需要一个静态列表
简单的说:IN(待扩展元素集) ,是不支持动态的子查询
即不能这样写IN (select 带扩展元素 from table)
所以带扩展元素集需要我们就直接罗列出来即可
SELECT * FROM PIVOT(SUN(Scores) FOR Subject IN (语文,数学,外语))
若是实际开发中,需要动态的 查询待扩展元素集
这就需要我们使用动态SQL取构建查询语句,并执行查询
1.准备测试数据
- 学生成绩表
----学生成绩表
IF OBJECT_ID('tempdb..#tempStudent') IS NOT NULL
BEGIN
DROP TABLE #tempStudent
END
CREATE TABLE #tempStudent
(
[Name] varchar(4),
[SubjectName] varchar(4),
[Scores] int,
[Class] varchar(10) )
INSERT INTO #tempStudent
VALUES
( '张三', '语文', 100, '八年级一班' ),
( '张三', '数学', 90, '三年级二班' ),
( '张三', '英语', 80, '三年级二班' ),
( '李四', '语文', 90, '三年级二班' ),
( '李四', '数学', 70, '三年级二班' ),
( '李四', '英语', 60, '三年级二班' )
- 考试科目表
----学生科目表
IF OBJECT_ID('tempdb..#tempSubject') IS NOT NULL
BEGIN
DROP TABLE #tempSubject;
END;
CREATE TABLE #tempSubject
(
[SubjectName] VARCHAR(4)
);
INSERT INTO #tempSubject
VALUES
('语文'),
('数学'),
('英语');
2.示例1——利用SELECT循环赋值
这里假定我们有单独的待扩展元素集的表,比如说这里我们有独立的课程名称表#tempSubject
所以我们可以单独的查询后拼接出静态的待扩展元素集
----拼接待扩展元素集
DECLARE @subjectStr VARCHAR(100)='';--注意一定要初始化为空字符串,才能实现下面的累加
SELECT @subjectStr=@subjectStr+SubjectName+',' FROM #tempSubject--拼接扩展元素集
SET @subjectStr =LEFT(@subjectStr,len(@subjectStr)-1)--删除拼接的最后一个逗号
SELECT @subjectStr--返回:语文,数学,英语
----将透视SQL语句定义为字符串,并执行
DECLARE @sql NVARCHAR(1000) = 'SELECT * FROM #tempStudent PIVOT(SUM(Scores) FOR [SubjectName] IN ({@subjectStr}))T';--使用“{@subjectStr}”做占位符
SET @sql = REPLACE(@sql, '{@subjectStr}', @subjectStr);--替换占位符
SELECT @sql;
EXEC sp_executesql @sql;
-- 结果
-- Name Class 语文 数学 英语
-- ---- ---------- ----------- ----------- -----------
-- 张三 八年级一班 100 NULL NULL
-- 李四 三年级二班 90 70 60
-- 张三 三年级二班 NULL 90 80
假设我们没有单独维护待扩展元素集的数据表,即这里没有提供#tempSubjcet
我看可以直接去重查询后#tempStudent中的SubjectName字段值,进行拼接
----拼接待扩展元素集
DECLARE @subjectStr VARCHAR(100) = '';
WITH cteSubject
AS
(
SELECT DISTINCT SubjectName FROM #tempStudent
)
SELECT @subjectStr = @subjectStr + SubjectName + ',' FROM cteSubject; --拼接扩展元素集
SET @subjectStr = LEFT(@subjectStr, LEN(@subjectStr) - 1); --删除拼接的最后一个逗号
SELECT @subjectStr; --返回:语文,数学,英语
--……后续操作如示例1
3.示例2——使用游标
- 若是有必要的话,可以使用游标拼接待扩展元素集
DECLARE @sql NVARCHAR(1000),
@subjectStr VARCHAR(1000),
@first INT;
--创建游标
DECLARE curStudent CURSOR FAST_FORWARD FOR
SELECT DISTINCT SubjectName FROM #tempStudent;
SET @first = 1;--标志变量:用于区分是否是第一个拼接字符串
SET @sql = N'SELECT * FROM #tempStudent PIVOT(SUM(Scores) FOR [SubjectName] IN (';
OPEN curStudent;
FETCH NEXT FROM curStudent INTO @subjectStr;
WHILE @@fetch_status = 0
BEGIN
IF @first = 0
SET @sql = @sql + N',';
ELSE
SET @first = 0;
SET @sql = @sql + @subjectStr;
FETCH NEXT FROM curStudent INTO @subjectStr;
END;
CLOSE curStudent;
DEALLOCATE curStudent;
SET @sql = @sql + N')) AS T;';
EXEC sp_executesql @sql;
4.示例3——使用FOR XML PATH()
其实针对构造"value1,value2,value3"格式的字符串,使用FOR XML PATH()函数配合STUFF()函数,是极其的方便
DECLARE @subjectStr VARCHAR(100);
WITH cteStudent AS
(
SELECT DISTINCT SubjectName FROM #tempStudent
)
SELECT @subjectStr= STUFF((SELECT ',' + SubjectName FROM cteStudent FOR XML PATH('')),1,1,'')
--这里@subjectStr=数学、英语、语文
DECLARE @sql NVARCHAR(1000) = 'SELECT * FROM #tempStudent PIVOT(SUM(Scores) FOR [SubjectName] IN ({@subjectStr}))T';--使用“{@subjectStr}”做占位符
SET @sql = REPLACE(@sql, '{@subjectStr}', @subjectStr);--替换占位符
SELECT @sql;
EXEC sp_executesql @sql;
5. 参考
T-SQL——透视PIVOT动态获取待扩展元素集的更多相关文章
- iwpriv工具通过ioctl动态获取相应无线网卡驱动的private_args所有扩展参数
iwpriv工具通过ioctl动态获取相应无线网卡驱动的private_args所有扩展参数 iwpriv是处理下面的wlan_private_args的所有扩展命令,iwpriv的实现上,是这样的, ...
- SQL中PIVOT 行列转换
来源:http://www.studyofnet.com/news/295.html PIVOT通过将表达式某一列中的唯一值转换为输出中的多个列来旋转表值表达式,并在必要时对最终输出中所需的任何其余列 ...
- map阶段动态获取CombineTextInputFormat各输入文件路径
老mr程序中map中conf的map.input.file参数只能获取获取CombineTextInputFormat的第一个输入文件,而新版mr程序则连第一个输入文件也无法获取,这是因为create ...
- sql:pivot unpivot
pivot 行转列 unpivot 列转行 源码跑步起来 这是能跑起来的 源码转自 http://www.cnblogs.com/zhangzt/archive/2010/07/29/178782 ...
- KTHREAD 线程调度 SDT TEB SEH shellcode中DLL模块机制动态获取 《寒江独钓》内核学习笔记(5)
目录 . 相关阅读材料 . <加密与解密3> . [经典文章翻译]A_Crash_Course_on_the_Depths_of_Win32_Structured_Exception_Ha ...
- Delphi泛型动态数组的扩展--转贴
此文章转载于http://www.raysoftware.cn/?p=278&tdsourcetag=s_pcqq_aiomsg的博客 从Delphi支持泛型的第一天起就有了一种新的动态数组类 ...
- MyBatis框架之SQL映射和动态SQL
使用MyBatis实现条件查询 1.SQL映射文件: MyBatis真正的强大之处就在于SQL映射语句,MyBatis专注于SQL,对于开发人员来说也是极大限度的进行SQL调优,以保证性能.下面是SQ ...
- delphi 动态获取文件类型的图标
delphi 动态获取文件类型的图标.txt我不奢望什么,只希望你以后的女人一个不如一个.真怀念小时候啊,天热的时候我也可以像男人一样光膀子!在应用程序的编写中,组合框(ComboBox).列表框(L ...
- js动态获取子复选项并设计全选及提交
在做项目的时候,会遇到根据父选项,动态的获取子选项,并列出多个复选框,提交时,把选中的合并成一个字符提交后台 本章将讲述如何通过js控制实现该操作: 1:设计父类别为radio,为每一个radio都加 ...
随机推荐
- Python代码阅读(第1篇):列表映射后的平均值
本篇阅读的代码实现了将列表进行映射,并求取映射后的平均值. 本篇阅读的代码片段来自于30-seconds-of-python. average_by def average_by(lst, fn=la ...
- 移动端动画——requestAnimationFrame
window.requestAnimationFrame() 告诉浏览器--你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画.该方法需要传入一个回调函数作为参数,该回调函数会 ...
- 微信小程序 转盘抽奖 倒计时 整点
xml: <view id="luckdraw_box"> <view id="luckdraw_back"> <image st ...
- MySQL中的seconds_behind_master的理解
通过show slave status查看到的Seconds_Behind_Master,从字面上来看,他是slave落后master的秒数,一般情况下,也确实这样,我们可以通过Seconds_Beh ...
- 三.Go微服务--令牌桶实现原理
1. 前言 在上一篇文章 Go微服务: 令牌桶 当中简单的介绍了令牌桶实现的原理,然后利用 /x/time/rate 这个库 10 行代码写了一个基于 ip 的 gin 限流中间件,那这个功能是怎么实 ...
- ES6扩展运算符(三点运算符)...的用法
1. 第一个叫做 展开运算符(spread operator),作用是和字面意思一样,就是把东西展开.可以用在array和object上都行. let a = [1,2,3]; let b = [0, ...
- TCP超时重传、序列号、滑动窗口简介
文章目录 12 TCP:传输控制协议(初步) 12.1 引言 12.1.1 ARQ和重传 12.1.2 分组窗口和滑动窗口 12.1.3 变量窗口:流量控制和拥塞控制 12.1.4 变量窗口:设置重传 ...
- Vue Abp vNext获取当前登录用户
系统默认提供了获取当前用户的api方法 https://localhost:44364/api/identity/my-profile 手工实现方法:abp后台获取当前用户需要在AppService应 ...
- 阶段总结-Java基础-超进阶
Gitee项目地址:https://gitee.com/zc10010/java_interview_guide/tree/master/知识点话术 项目叫话术,但是我觉得作为知识点学习是挺不错的. ...
- 大数据最后一公里——2021年五大开源数据可视化BI方案对比
个人非常喜欢这种说法,最后一公里不是说目标全部达成,而是把整个路程从头到尾走了一遍. 大数据在经过前几年的野蛮生长以后,开始与数据中台的概念一同向着更实际的方向落地.有人问,数据可视化是不是等同于数据 ...