T-SQL——透视PIVOT动态获取待扩展元素集
2021-10-08 01:00
621 查看
目录
志铭-2021年10月8日 00:57:00
0.背景说明
在< 56c a href="https://www.cnblogs.com/shanzhiming/p/15371249.html" target="_blank">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) ) INSER ad0 T 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; --返回:语文,数学,英语 --……后续操作如示例1200a
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——动态SQL
- T-SQL——基础语法
- T-SQL——游标
- T-SQL——XML
相关文章推荐
- 关于js/jq对动态创建元素获取不到的问题分析讨论及扩展
- 动态SQL解决PIVOT透视多列的问题
- mysql存储过程 在动态SQL内获取返回值的方法详解
- jQuery获取动态添加的元素,live和on的区别
- SQL动态获取列名进行查询
- 简单搞一下 Oracle 存储过程动态SQL之获取查询总数!
- iwpriv工具通过ioctl动态获取相应无线网卡驱动的private_args所有扩展参数
- 在PL/SQL使用游标获取数据及动态SQL
- 如何在T-SQL中获取逗号分割的字符串数据中的元素?
- 关于JS获取不到动态创建的元素的id的问题
- jquery 简短几句代码实现给元素动态添加及获取提示信息
- JQuery获取append后的动态元素
- 增加和获取SQL扩展属性
- Android Manifest中meta-data扩展元素数据的配置与获取方式
- mysql存储过程在动态SQL内获取返回值
- JQuery获取append后的动态元素:live()和on()
- 动态SQL语法及获取本周、本月、本年时间段值
- jquery 简短几句代码实现给元素动态添加及获取提示信息
- sql动态获取每日0点日期(不用字符串拼接)presto
- Linq扩展方法获取单个元素