首页 > 数据库 >SQL Server 多行合并成一行,逗号分隔实现

SQL Server 多行合并成一行,逗号分隔实现

时间:2023-05-07 14:24:20浏览次数:37  
标签:xml Server 逗号 Score Student SQL path where select

我们写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  

效果如下图

结束

 

标签:xml,Server,逗号,Score,Student,SQL,path,where,select
From: https://www.cnblogs.com/dyhuang/p/17379209.html

相关文章

  • mysql执行顺序
    Mysql语法顺序,即当sql中存在下面的关键字时,它们要保持这样的顺序: select[distinct]fromjoin(如leftjoin)onwheregroupbyhavingunionorderbylimit  Mysql执行顺序,即在执行时sql按照下面的顺序进行执行: from......
  • [docker]mysql的docker镜像中docker-entrypoint-initdb.d目录的妙用
    docker-entrypoint-initdb.d是Docker官方MySQL镜像中的一个目录,用于初始化数据库。在该目录下,可以放置一些SQL脚本文件,MySQL会在容器启动时自动执行这些脚本文件,用于创建用户、创建数据库、创建表等操作。具体来说,当MySQL镜像启动时,其entrypoint.sh脚本会检查是否存在......
  • LDAP备份迁移和LDAP主从配置,阿里云服务器做主,内网机做从,zabbix,gilab,jumpserver接入lda
    一,LDAP备份迁移1,原服务器上导出备份文件mkdir/opt/ldap/usr/sbin/slapcat>/opt/ldap/ldapdbak.ldif2,目标服务器搭建ldap环境yuminstallopenldapopenldap-clientsopenldap-serversserviceslapdstartsystemctlenableslapdslappasswd-h{SSHA}-sxxxxx #生成管理......
  • 神奇的 SQL 之 CASE表达式,妙用多多 !
    CASE表达式之概念相信大家都用过CASE表达式,尤其是做一些统计功能的时候,用的特别多,可真要说什么是CASE表达式,我估计还真没几个人能清楚的表述出来。CASE表达式和“2+1”或者“120/3”这样的表达式一样,是一种进行运算的功能,正如CASE(情况)这个词的含义一样,用于区分情况,在有......
  • 在本机有MYSQL57的情况下安装MYSQL80
    下载MYSQL80https://dev.mysql.com/downloads/mysql/需要ORACLE账号配置环境变量加一个环境变量MYSQL_HOME80值为自己的放置解压的MYSQL80的根目录路径在PATH中配置环境变量%KEY%可以索引到刚才在外面配置的路径的内容,然后加上\bin,\bin中有可执行的批处理脚本将80的环境......
  • Linux deplay 安装 Ubuntu 及 MySQL
    设备支持:已root的mi-4(架构:armv71)软件支持:LinuxDeplay在Linuxdeplay上安装好你希望安装的Linux版本,我这里安装的是Ubuntu18.04(bionic),注意要根据手机的处理器型号选择适配的处理器版本,由于mi-4的处理器是armv71,发行版本选择armhfARMCortex-A系列(A53、A57、......
  • MySQL数据优化
    select*fromstudent;deletefromstudent;SELECTCOUNT(1)fromstudent;SELECT*FROM`student`LIMIT10000,10--0.674s--0.033s--0.031sSELECT*FROM`student`LIMIT10000,10;--0.031sSELECT*FROM`student`LIMIT10000,100;--0.032sSELECT*FROM......
  • 软件测试|一文告诉你SQL到底是什么
    前言我们在学习数据库时,第一个要弄明白的东西就是,SQL是什么,SQL是StructuredQueryLanguage的缩写,字面意思为“结构化查询语言”,它可以用来进行数据的查询、插入、更新、删除等操作,也可以用于创建和管理数据库对象,如表、视图、存储过程、函数等。本篇文章我们就将对SQL进行系统......
  • mysql error 1064(42000)
    mysql表里面,使用同样的语法查询一张表,用的nopcommerce的表,里面的Order表,查询的时候出不来,总是提示1064(42000说语法有错误,思考不会有错,于是查询这个问题,也有想过这张表名有些特殊, 查询要加反单引号,select*from`Order`;就查询出来了,可能Order是一个关键......
  • 逗号的祸
    问题代码报错:[Error]expectedunqualified-idbefore'long'[Note]inexpansionofmacro'll'#include<cctype>#include<cmath>#include<cstdio>#include<cstring>#include<iostream>#include<algorith......