我们写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 多行合并成一行,逗号分隔,拆解分析实现原理的更多相关文章

  1. SQL Server将同一列多条数据合并成一行

    Sql server中,将同一字段多条数据用字符拼接为一个字符串方式. 原数据查询展示: 使用 STUFF 函数,将结果列拼接成一行.结果如下: STUFF: 1.作用 stuff(param1, s ...

  2. ELK之使用filebeat的多行过滤插件把多行合并成一行

    java运行日志一般有多行,格式类似如下 格式为:日期 + 日志级别 + 日志信息 有些日志是多行的,需要使用filebeat多行插件把多行合并成一行 未使用多行插件的日志格式 修改filebeat配 ...

  3. sql server的for xml path与变通的行转列

    SQL Server中有提供一个FOR XML PATH的子句(不知道能不能叫函数),用来将查询结果行输出成XML格式,我们可以通过这个语法做一些变通实现一些特定的功能,比如说行转列.要会变通的话,当 ...

  4. sql server 使用for xml path 将1列多行转换为字符串连接起来,俗称 sql 合并字符

    由于项目的原因,需要将一些记录分类汇总,但还要列出相关的明细,这样的需求我还是第一次遇到,蛋疼了,还是请求一下度娘吧.搜索一番还是有结果,请看以下例子: create table tb ([id] i ...

  5. sql server 使用for xml path 将1列多行转换为字符串连接起来

    create table tb ([id] )) insert into tb ,'aa' union all ,'bb' union all ,'cc' union all ,'dd' union ...

  6. Sql Server 之 for xml (path,raw,auto,root)

    1.for xml path('str') select ID,CreateTime  from dbo.ArticleInfo for xml Path('mytitle') 结果:(注意:如果是s ...

  7. SQL语句 分组 多行合并成一行

    ,,'')) FROM Table d GROUP by Id 另外: sql 单引号转义:两个单引号转义为一个单引号 set @sql='STUFF((SELECT '','' + Names FR ...

  8. sql多行合并成一行用逗号隔开,多表联合查询中子查询取名可重复

    简单版的 SELECT a.CreateBy,Name =stuff((select ','+Name FROM SG_Client WHERE CreateBy = a.CreateBy for x ...

  9. logstash收集java日志,多行合并成一行

    使用codec的multiline插件实现多行匹配,这是一个可以将多行进行合并的插件,而且可以使用what指定将匹配到的行与前面的行合并还是和后面的行合并. 1.java日志收集测试 input { ...

  10. SQL Server select 将类型相同的行合并,并将对应金额相加

    select Category,REPLACE(sum(Amount),'-','')  as Amountfrom T_Detail WHERE CREATED_BY='6123EC14-50E2- ...

随机推荐

  1. DevEco Hvigor高效编译,构建过程新秘籍

      作者:Lewei,华为终端BG编译构建技术专家 DevEco Hvigor是使用TypeScript语言开发的全新轻量化的任务调度工具,针对HarmonyOS应用提供了一系列编译构建任务,支持将H ...

  2. 【直播预告】HarmonyOS 极客松赋能直播第六期:产品创新从哪里来?

  3. js es6 Iterator

    1.遍历器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制.任何数据结构只要部署Iterator接口,就可以完成遍历操作(即依次处理该数据结构的所有成员). 2.Iterator ...

  4. CTFshow命令执行29-123

    命令执行 WEB29 eval是php中执行以PHP脚本执行的命令 PHP命令可以执行脚本命令 本题使用方法是先 system(cp f*.php 1.txt) 然后访问1.txt WEB30 在PH ...

  5. 《c#高级编程》第2章C#2.0中的更改(三)——迭代器

    一.概念 C#迭代器(Iterator)是一种特殊类型的方法,它使得在使用循环遍历数据集合时更加简单和有效.使用迭代器可以通过简单地定义迭代器方法来自动实现枚举器模式. 当您需要访问一个数据集合中的每 ...

  6. Java 断言 Assert 使用教程与最佳实践

    本文收录于 Github.com/niumoo/JavaNotes,Java 系列文档,数据结构与算法! 本文收录于网站:https://www.wdbyte.com/,我的公众号:程序猿阿朗 作为一 ...

  7. PolarDB-X 2.1 新版本发布 让“MySQL 原生分布式”触手可及

    简介: PolarDB-X 2.1 是 PolarDB-X 非常重要的版本,也是第一次 PolarDB-X 分布式数据库的产品可以作为企业级的分布式数据库真正部署到客户的生产环境使用. PolarDB ...

  8. 系列解读SMC-R:透明无感提升云上 TCP 应用网络性能(一)| 龙蜥技术

    ​简介:已有的应用若想使用RDMA技术改造成本高,那么有没有一种技术是不做任何改造就可以享受RDMA带来的性能优势? ​ 文/龙蜥社区高性能网络SIG 引言 Shared Memory Communi ...

  9. [FAQ] MEMORY ALLOC FAILED: mmap with HUGETLB failed, attempting without it (you should fix your kernel)

    cat /proc/meminfo | grep Huge sysctl vm.nr_hugepages=128 cat /proc/meminfo | grep Huge Link:https:// ...

  10. dotnet C# 通过 Vortice 使用 Direct2D 特效入门

    本文将告诉大家如何通过 Vortice 使用 D2D 的特效 本文属于 DirectX 系列博客,更多 DirectX 和 D2D 以及 Vortice 库的博客,请参阅我的 博客导航 上一篇: Di ...