SQL Server使用for xml path 多行合并成一行,逗号分隔,拆解分析实现原理
我们写sql脚本处理数据的时候 针对部分数据进行group by 分组,分组后需要将部分数据放入分组后的行里面以逗号分隔。
举一个简单例子:

如上图的数据,需要对学生进行分组,取得学生都参与了哪些学科的考试和 所有总分。
如下图这种数据

目前有两种方案,
1. 在SQL Server 2017版本 已经提供了现成的string_agg函数 使用方式比较简单,但有版本限制,需要注意。
代码如下:
select
Student
,subjects=STRING_AGG(Subject,',')
,totalScore=SUM(score)
from
Score a
group by Student
2. 另一种是使用SQL Server的 for xml path 加上分割符的方法取得,这种是比较常见的,兼容性也比较强
select
Student
,Subjects=stuff((select ','+convert(varchar, [subject])
from Score b
where 1=1
and b.Student= a.Student
for xml path('')), 1, 1, '')
,totalScore=SUM(score)
from
Score a
group by Student
如上图是具体实现,但该代码是如何实现呢。我们今天具体拆解并分析下实现过程。
我们分步骤进行拆解
1. 先进行一个简单的查询
select *
from Score b
where 1=1
and b.Student=N'李四'

2. 使用for xml path 将多行数据拆解到一行中
select *
from Score b
where 1=1
and b.Student=N'李四'
for xml path
得到如下图这种数据形式,将数据拆成 xml 放在了一列中


3. 因为我们只需要学科,所以我们只查询学科字段即可
select [subject]
from Score b
where 1=1
and b.Student=N'李四'
for xml path
得到如下图数据


4. 接下来是处理其中的xml 节点,有没有办法可以直接去掉对应的 【学科】也就是 <subject></subject>的标签呢
select convert(varchar, [subject])
from Score b
where 1=1
and b.Student=N'李四'
for xml path
根据如上sql脚本,
主要是使用了convert函数,将subject 列改为【无列名】 这种方式就会取消 <subject>标签显示,当然其他任意方式都可以。只要是无列名即可。
效果如下图


这就取消掉了xml中 subject显示
5. 接下来是考虑 如何取消 row标签的显示呢?
SQL Server 提供的 for xml path 中,如果 在path() 后 修改为如 path('myrow') 则可以修改 <row>标签显示。
select convert(varchar, [subject])
from Score b
where 1=1
and b.Student=N'李四'
for xml path ('myrow')
效果图如下


这样就可以修改 row的显示了
6. 那么如何才能不显示row节点呢,其实很简单那,使用 for xml path ('') 即可
具体如下
select convert(varchar, [subject])
from Score b
where 1=1
and b.Student=N'李四'
for xml path ('')
效果图


至此 就可以实现 将 多行数据放在一列中,接下来是考虑要以逗号分隔。
7. 逗号分隔只需要前面加上逗号字符串即可。
select ','+ convert(varchar, [subject])
from Score b
where 1=1
and b.Student=N'李四'
for xml path ('')
效果如下图


8. 由于我们不需要xml这种列名,需要的是自定义列名如何处理呢,其实也很简单
在select前面再加上select 即可。
select
(select ','+convert(varchar, [subject])
from Score b
where 1=1
and b.Student=N'李四'
for xml path(''))
效果如下图,当然你也可以自定义列名,如 subjects

9. 这时候需要考虑去掉最前面的逗号字符串了
使用SQL Server 的函数 stuff 即可,stuff函数这里就不具体讲了。
select subjects=stuff((select ','+convert(varchar, [subject])
from Score b
where 1=1
and b.Student=N'李四'
for xml path('')), 1, 1, '')
效果如下图

10 接下来只需要将以上脚本放入 我们主查询的语句中即可。
放入我们select的子查询脚本中
select
*
,Subjects=stuff((select ','+convert(varchar, [subject])
from Score b
where 1=1
and b.Student= a.Student
for xml path('')), 1, 1, '') from
Score a
效果如下图

11. 这时候直接进行 group by语句就好了
select
Student
,Subjects=stuff((select ','+convert(varchar, [subject])
from Score b
where 1=1
and b.Student= a.Student
for xml path('')), 1, 1, '')
,totalScore=SUM(score)
from
Score a
group by Student
效果如下图

结束
SQL Server使用for xml path 多行合并成一行,逗号分隔,拆解分析实现原理的更多相关文章
- SQL Server将同一列多条数据合并成一行
Sql server中,将同一字段多条数据用字符拼接为一个字符串方式. 原数据查询展示: 使用 STUFF 函数,将结果列拼接成一行.结果如下: STUFF: 1.作用 stuff(param1, s ...
- ELK之使用filebeat的多行过滤插件把多行合并成一行
java运行日志一般有多行,格式类似如下 格式为:日期 + 日志级别 + 日志信息 有些日志是多行的,需要使用filebeat多行插件把多行合并成一行 未使用多行插件的日志格式 修改filebeat配 ...
- sql server的for xml path与变通的行转列
SQL Server中有提供一个FOR XML PATH的子句(不知道能不能叫函数),用来将查询结果行输出成XML格式,我们可以通过这个语法做一些变通实现一些特定的功能,比如说行转列.要会变通的话,当 ...
- sql server 使用for xml path 将1列多行转换为字符串连接起来,俗称 sql 合并字符
由于项目的原因,需要将一些记录分类汇总,但还要列出相关的明细,这样的需求我还是第一次遇到,蛋疼了,还是请求一下度娘吧.搜索一番还是有结果,请看以下例子: create table tb ([id] i ...
- sql server 使用for xml path 将1列多行转换为字符串连接起来
create table tb ([id] )) insert into tb ,'aa' union all ,'bb' union all ,'cc' union all ,'dd' union ...
- Sql Server 之 for xml (path,raw,auto,root)
1.for xml path('str') select ID,CreateTime from dbo.ArticleInfo for xml Path('mytitle') 结果:(注意:如果是s ...
- SQL语句 分组 多行合并成一行
,,'')) FROM Table d GROUP by Id 另外: sql 单引号转义:两个单引号转义为一个单引号 set @sql='STUFF((SELECT '','' + Names FR ...
- sql多行合并成一行用逗号隔开,多表联合查询中子查询取名可重复
简单版的 SELECT a.CreateBy,Name =stuff((select ','+Name FROM SG_Client WHERE CreateBy = a.CreateBy for x ...
- logstash收集java日志,多行合并成一行
使用codec的multiline插件实现多行匹配,这是一个可以将多行进行合并的插件,而且可以使用what指定将匹配到的行与前面的行合并还是和后面的行合并. 1.java日志收集测试 input { ...
- SQL Server select 将类型相同的行合并,并将对应金额相加
select Category,REPLACE(sum(Amount),'-','') as Amountfrom T_Detail WHERE CREATED_BY='6123EC14-50E2- ...
随机推荐
- 数仓调优实战:GUC参数调优
本文分享自华为云社区<GaussDB(DWS)性能调优系列实战篇七:十八般武艺之GUC参数调优>,作者: 黎明的风. 1. 前言 适用版本:[8.1.1及以上] GaussDB(DWS)性 ...
- Groovy反序列化链分析
前言 Groovy 是一种基于 JVM 的开发语言,具有类似于 Python,Ruby,Perl 和 Smalltalk 的功能.Groovy 既可以用作 Java 平台的编程语言,也可以用作脚本语言 ...
- 国内十大活跃报表 BI 产品深度点评
目前国内市场上的报表 BI 工具琳琅满目,看起来也各有特点,这给选型工作带来了一些困扰,本文就一些较活跃的报表 BI 产品进行点评,对于不太熟悉这些产品和技术的同学,可作为参考资料. 这里选了十个产品 ...
- c# MCV 实现跨域
前言 core跨域严格来说是要分为两步的,因为分为简单跨域和复杂跨域,第一种为直接允许跨域,第二种因为存在某些框架本身不允许put,delete这两个,那么这就是一个问题了.对的,那么mvc这种重量级 ...
- Lattice Crosslink开发简介
选择lattice的Crosslink器件,大多是因为它功耗比较低.价格便宜,开发也比较简单,相对来说更容易上手.大部分用在手机屏,摄像头模组和平板方面. Crosslink的开发工具是Diamond ...
- 【c++】类valarray介绍
valarray类用于处理数组中的数值,如将所有元素相加,找出最大.最小值,数组长度. 如何使用valarray类: 1.首先需要声明头文件 #include<valarray&g ...
- 从源码入手详解ReentrantLock,一个比synchronized更强大的可重入锁
写在开头 随手一翻,发现对于Java中并发多线程的学习已经发布了十几篇博客了,多线程 是Java基础中的重中之重!因此,可能还需要十几篇博客才能大致的讲完这部分的知识点,初学者对于这部分内容一定要多花 ...
- 力扣7(java)-整数反转(中等)
题目: 给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果. 如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0. 假设环境不允许存 ...
- [GPT] jquery chosen插件选择的多个元素是逗号分隔的,怎么设置成其它分隔符号 ?
如果你想要在 jQuery Chosen 插件中使用其它分隔符号,可以通过以下方式实现: 1. 设置 delimiter 选项为一个包含所需分隔符的字符串. $(".chosen-selec ...
- [FAQ] Win10 找到打开 hosts 文件
1. Win+R 打开运行窗口. 2. 输入命令 C:\Windows\System32\drivers\etc 回车. Refer:windows hosts Link:https://www.cn ...