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

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

时间:2023-07-28 16:12:34浏览次数:42  
标签: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/telwanggs/p/17587908.html

相关文章

  • SQL Server CURRENT_TIMESTAMP()实例讲解
    CURRENT_TIMESTAMP()函数:SQLServer中的此函数用于返回当前日期和时间。输出的格式如下。'YYYY-MM-DDhh:mm:ss.mmm'特征:此函数用于查找当前日期和时间。此函数位于日期函数下。此函数不接受任何参数。在某些代码中,该函数也可以用作默认值。用法:CURRENT_TIMESTAMP......
  • 基于 Kubernetes 部署 MySQL 数据库
    本文将介绍如何基于Kubernetes部署MySQL数据库。创建服务Service创建一个Service为即将部署的MySQL数据库固定连接的IP,同时提供负载均衡,下面是mysql-service.yaml文件的内容: yaml复制代码apiVersion:v1kind:Servicemetadata:name:mysqlspec:s......
  • 数据源为postgresSQL的docker版nacos
    1.首先编写Dcokerfile,基础镜像为ubuntu:18.04,安装Java环境等FROMubuntu:18.04ENVJAVA_DIR=/usr/localENVJAVA_HOME=$JAVA_DIR/java8ENVPATH=$PATH:$JAVA_HOME/binENVNACOS_VERSION=2.2.0.1ENVNACOS_HOME=/nacos#安装jdkCOPY./jdk-8u11-linux-x64.tar.gz$JAVA......
  • mysql 中的 having 与 order by 的区别与联系举例说明
    HAVING和ORDERBY都是在查询语句中用于对结果进行排序的子句,但它们的使用场景和作用略有不同。区别:HAVING子句用于在GROUPBY子句后对分组结果进行筛选,只返回满足条件的分组。它通常与聚合函数一起使用,用于筛选分组后的结果集。HAVING子句是在分组后进行筛选,可以使用聚合函数和......
  • mysql 的左连结 右边结 内连结 外连结和全连结的区别及使用场景举例
    在MySQL中,左连接(LEFTJOIN)、右连接(RIGHTJOIN)、内连接(INNERJOIN)、外连接(OUTERJOIN)和全连接(FULLJOIN)是常用的连接操作,用于联接多个表。这些连接操作的区别如下:左连接(LEFTJOIN):返回左表中的所有记录,以及与右表中匹配的记录。如果右表没有匹配的记录,则返回NULL值。左连接使用L......
  • 写一条mysql更新数据的语句
    要更新MySQL数据库中的数据,你可以使用UPDATE语句。下面是一个示例代码,用于更新数据库中的数据:importmysql.connectordefupdate_data(connection,table,column,value,condition):cursor=connection.cursor()#构造更新数据的SQL语句update_query=f"UP......
  • mysql中子查询和连接操作的使用场景和区别是什么?请举例说明?
    MySQL中的子查询和连接操作都是用于联接多个表或查询结果,但它们有不同的使用场景和区别。子查询是指在一个查询中嵌套另一个查询,内部查询的结果作为外部查询的条件或数据源。子查询通常用于获取特定条件下的数据,或者用于计算某个字段的值。连接操作是指通过联接多个表来获取相关......
  • mysql中in的使用场景及用法举例说明?
    在MySQL中,IN运算符用于在WHERE子句中指定一个条件,以便从一个给定的列表中选择满足条件的值。IN运算符可以用于任何数据类型,包括数字、字符串和日期。下面是IN运算符的使用场景和用法的示例说明:使用IN运算符筛选特定值:查询订单表中订单状态为"已发货"或"已完成"的订单:SELECT......
  • mysql8.0环境的搭建(Linux)
    1.安装前说明1.1Linux系统及工具的准备。安装并启动好两台虚拟机:CentOS7安装有远程访问centOS系统的工具CentOS6和CentOS7在MySQL的使用中的区别默认防火墙:CentOS6是iptables;CentOS7是firewalld;启动服务的命令:CentOS6是servicemysqldstart;CentOS7是systemctlstart......
  • 内网环境windows server 2012r2系统怎样手动安装cab更新补丁
    在内网部署了几台winserver2012r2服务器,由于是纯内网,要求和互联网物理隔离,内网的服务器更新补丁成了一个问题,在互联网上没有找到单独的集成补丁包,去微软官方手动下载再去更新费时费力,便想到使用以下方法进行。1、使用互联网台式机安装一台虚拟机,虚拟机要求和内网服务器使用相......