参考资料:

http://www.cnblogs.com/doubleliang/archive/2011/07/06/2098775.html

http://www.cnblogs.com/codeyu/archive/2010/05/25/1743474.html

核心摘要

FOR XML PATH 的作用是把结果以xml文本的形式显示出来,也就是说,最终结果就是一个字符串,因此我们就不需要使用什么字符串合并函数了。

STUFF函数的原型是 Stuff(str1, start, len, str2),作用是,删掉str1中start开始的len个字符,用str2替换。因此,可以起到在多个项之间插入分隔符。

比如,

select ','+name from student for xml path('') group by class

输出结果可能是

,Jim,Kate,Tom,Sally

如果使用STUFF,可以删掉第一个空格

stuff(select ','+name from student for xml path('') group by class, 1, 1, '')

原文内容

-------------参考------------------------

----假设我们有如下数据表
------菜系表------------
--店名        菜系------
--澳门豆捞    川菜 
--澳门豆捞    粤菜 
--澳门豆捞    闽菜 
--为民大酒店  鲁菜 
--为民大酒店  粤菜 
--为民大酒店  川菜
-----------------------

-------执行如下语句
select 店名,菜系=STUFF((select ','+ltrim(菜系) from 菜系表 where 店名=t.店名 for XML path('')),1,1,'')
from 菜系表 t
group by 店名

-------结果如下-------------
--店名        菜系----------
--澳门豆捞    川菜,闽菜,粤菜
--为民大酒店  川菜,鲁菜,粤菜
----------------------------

--------------------------------------------------------------------------------------
Stuff(expression1_Str,startIndex,lengthInt,expression2_Str)函数共有四个参数,
其功能是将expression1_Str中自startIndex位置起删除lengthInt个字符,然后将expression2插入到expression1_Str中的startIndex位置。startIndex 从1开始
数据库表中有三个字段,要以xxxx-xxxxxx-xxxxxx的格式输出,其中不满相应位数的,在后面补空格,即把类似23,1234,879这样的三个数以如下形式输出到报表中:23__-1234__-879___的格式输出,标注颜色的下划线一种颜色代表一个空格。 
STUFF(SPACE(4),1,LEN(‘23’),’23’)+’-’+STUFF(SPACE(6),1,LEN(‘1234’),’1234’)+’-’+ STUFF(SPACE(6),1,LEN(‘879’),’879’),转换结果自然就为23__-1234__-879___了。
Stuff函数另一种解释
select stuff('string1',<starting position>,<length to delete from string 1>,'string2')
示例:
select stuff('youxiaofeng',2,1,'F')
从第二个字符开始,删掉一个字符,然后用'F'代替删掉字符的位置,如果不需要删掉字符,则将<length to delete from string 1>设为0即可。
注意:如果<starting position>或<length to delete from string 1 >是负的,或者<starting position>是大于<string 1>长度的数,则STUFF函数将返回NULL,如果指令的<length to delete from string 1>长于从<starting position>位置到<string 1>结尾的字符数,此函数将<string 1 >在<starting position-1>处截断

---------------------------------------------------------------------------
FOR XML PATH 语句的应用
大家都知道在SQL Server中利用 FOR XML PATH 语句能够把查询的数据生成XML数据,下面是它的一些应用示例。

DECLARE @TempTable table(UserID int , UserName nvarchar(50));
insert into @TempTable (UserID,UserName) values (1,'a')
insert into @TempTable (UserID,UserName) values (2,'b')

select UserID,UserName from @TempTable FOR XML PATH
运行这段脚本,将生成如下结果:

<row>
<UserID>1</UserID>
<UserName>a</UserName>
</row>
<row>
<UserID>2</UserID>
<UserName>b</UserName>
</row>
大家可以看到两行数据生成了两个节点,修改一下PATH的参数:

select UserID,UserName from @TempTable FOR XML PATH('lzy')
再次运行上述脚本,将生成如下的结果:

<lzy>
<UserID>1</UserID>
<UserName>a</UserName>
</lzy>
<lzy>
<UserID>2</UserID>
<UserName>b</UserName>
</lzy>
可以看到节点变成,其实PATH() 括号内的参数是控制节点名称的,这样的话大家可以看一下如果是空字符串(不是没有参数)会是什么结果?

select UserID,UserName from @TempTable FOR XML PATH('')
执行上面这段脚本将生成结果:

<UserID>1</UserID>
<UserName>a</UserName>
<UserID>2</UserID>
<UserName>b</UserName>
这样就不显示上级节点了,大家知道在 PATH 模式中,列名或列别名被作为 XPath 表达式来处理,也就是说,是列的名字,这样大胆试验一下不给指定列名和别名会是怎么样?

select CAST(UserID AS varchar) + '',UserName + '' from @TempTable FOR XML PATH('')
运行上面这句将生成结果

1a2b

所有数据都生成一行,而且还没有连接字符,这样的数据可能对大家没有用处,还可以再变化一下:

select CAST(UserID AS varchar) + ',',UserName + '',';' from @TempTable FOR XML PATH('')
生成结果

1,a;2,b;

大家现在明白了吧,可以通过控制参数来生成自己想要的结果,例如:

select '{' + CAST(UserID AS varchar) + ',','"' +UserName + '"','}' from @TempTable FOR XML PATH('')
生成结果

{1,"a"}{2,"b"}

还可以生成其他格式,大家可以根据自己需要的格式进行组合。

下面是一个数据统计的应用,希望大家可以通过下面的实例想到更多的应用

DECLARE @T1 table(UserID int , UserName nvarchar(50),CityName nvarchar(50));
insert into @T1 (UserID,UserName,CityName) values (1,'a','上海')
insert into @T1 (UserID,UserName,CityName) values (2,'b','北京')
insert into @T1 (UserID,UserName,CityName) values (3,'c','上海')
insert into @T1 (UserID,UserName,CityName) values (4,'d','北京')
insert into @T1 (UserID,UserName,CityName) values (5,'e','上海')

SELECT B.CityName,LEFT(UserList,LEN(UserList)-1) FROM (
SELECT CityName,
(SELECT UserName+',' FROM @T1 WHERE CityName=A.CityName FOR XML PATH('')) AS UserList
FROM @T1 A 
GROUP BY CityName
) B
生成结果(每个城市的用户名)

北京 b,d
上海 a,c,e

灵活运用 SQL SERVER FOR XML PATH

FOR XML PATH 有的人可能知道有的人可能不知道,其实它就是将查询结果集以XML形式展现,有了它我们可以简化我们的查询语句实现一些以前可能需要借助函数活存储过程来完成的工作。那么以一个实例为主.

一.FOR XML PATH 简单介绍

             那么还是首先来介绍一下FOR XML PATH ,假设现在有一张兴趣爱好表(hobby)用来存放兴趣爱好,表结构如下:

接下来我们来看应用FOR XML PATH的查询结果语句如下:

SELECT*FROM@hobbyFORXML PATH

结果:

<row>
  <hobbyID>1</hobbyID>
  <hName>爬山</hName>
</row>
<row>
  <hobbyID>2</hobbyID>
  <hName>游泳</hName>
</row>
<row>
  <hobbyID>3</hobbyID>
  <hName>美食</hName>
</row>

由此可见FOR XML PATH 可以将查询结果根据行输出成XML各式!

那么,如何改变XML行节点的名称呢?代码如下:

SELECT*FROM@hobbyFORXML PATH('MyHobby')

结果一定也可想而知了吧?没错原来的行节点<row> 变成了我们在PATH后面括号()中,自定义的名称<MyHobby>,结果如下:

<MyHobby>
  <hobbyID>1</hobbyID>
  <hName>爬山</hName>
</MyHobby>
<MyHobby>
  <hobbyID>2</hobbyID>
  <hName>游泳</hName>
</MyHobby>
<MyHobby>
  <hobbyID>3</hobbyID>
  <hName>美食</hName>
</MyHobby>

这个时候细心的朋友一定又会问那么列节点如何改变呢?还记的给列起别名的关键字AS吗?对了就是用它!代码如下:

SELECThobbyID as'MyCode',hName as'MyName'FROM@hobbyFORXML PATH('MyHobby')

那么这个时候我们列的节点名称也会编程我们自定义的名称 <MyCode>与<MyName>结果如下:

<MyHobby>
  <MyCode>1</MyCode>
  <MyName>爬山</MyName>
</MyHobby>
<MyHobby>
  <MyCode>2</MyCode>
  <MyName>游泳</MyName>
</MyHobby>
<MyHobby>
  <MyCode>3</MyCode>
  <MyName>美食</MyName>
</MyHobby>

噢! 既然行的节点与列的节点我们都可以自定义,我们是否可以构建我们喜欢的输出方式呢?还是看代码:

SELECT'[ '+hName+']'FROM@hobbyFORXML PATH('')

没错我们还可以通过符号+号,来对字符串类型字段的输出格式进行定义。结果如下:

[ 爬山 ][ 游泳 ][ 美食 ]

那么其他类型的列怎么自定义? 没关系,我们将它们转换成字符串类型就行啦!例如:

SELECT'{'+STR(hobbyID)+'}','[ '+hName+']'FROM@hobbyFORXML PATH('')

好的 FOR XML PATH就基本介绍到这里吧,更多关于FOR XML的知识请查阅帮助文档!

接下来我们来看一个FOR XML PATH的应用场景吧!那么开始吧。。。。。。

        二.一个应用场景与FOR XML PATH应用

        首先呢!我们在增加一张学生表,列分别为(stuID,sName,hobby),stuID代表学生编号,sName代表学生姓名,hobby列存学生的爱好!那么现在表结构如下:

这时,我们的要求是查询学生表,显示所有学生的爱好的结果集,代码如下:

SELECTB.sName,LEFT(StuList,LEN(StuList)-1) ashobby FROM(
SELECTsName,
(SELECThobby+','FROMstudent 
  WHEREsName=A.sName 
  FORXML PATH('')) ASStuList
FROMstudent A 
GROUPBYsName
) B 

结果如下:

分析: 好的,那么我们来分析一下,首先看这句:

SELECThobby+','FROMstudent 
  WHEREsName=A.sName 
  FORXML PATH('')

这句是通过FOR XML PATH 将某一姓名如张三的爱好,显示成格式为:“ 爱好1,爱好2,爱好3,”的格式!

那么接着看:

SELECTB.sName,LEFT(StuList,LEN(StuList)-1) ashobby FROM(
SELECTsName,
(SELECThobby+','FROMstudent 
  WHEREsName=A.sName 
  FORXML PATH('')) ASStuList
FROMstudent A 
GROUPBYsName
) B  

剩下的代码首先是将表分组,在执行FOR XML PATH 格式化,这时当还没有执行最外层的SELECT时查询出的结构为:

可以看到StuList列里面的数据都会多出一个逗号,这时随外层的语句:SELECT B.sName,LEFT(StuList,LEN(StuList)-1) as hobby  就是来去掉逗号,并赋予有意义的列明!

好啦,太晚啦就说到这里吧!

转载于:https://www.cnblogs.com/dabaopku/archive/2012/07/18/2597237.html

使用 FOR XML PATH 合并SQL Server查询结果的重复行相关推荐

  1. SQL Server查询、限制返回行数

    我们在日常开发中,经常涉及到分页查询.特别是和页面进行交互,分页查询已是家常便饭. 现在很多的jq插件都会有分页的模块,可以在页面上将数据更好的呈现给用户,使得用户拥有更好的体验.像我们熟悉的有很多, ...

  2. 如何删除SQL Server表中的重复行

    若在你的MS Sql Server数据库表中,有重复的多行,你可能想去删除这些重复的记录. T_SQL Row_Number()函数能帮助sql开发者去解决这个sql的问题. 1.创建TUser表: ...

  3. SQL SERVER 查询、删除重复数据

    查询删除重复数据,只保留一条记录: 1.根据单字段,查询表中该字段重复出现记录: SELECT * FROM Table WHERE Parameter IN (SELECT Parameter FR ...

  4. Sql Server查询性能优化之索引篇【推荐】

    Sql Server查询性能优化之索引篇[推荐] 这篇是索引系列中比较完整的,经过整理而来的 一 索引基础知识 索引概述 1.概念 可以把索引理解为一种特殊的目录.就好比<新华字典>为了加 ...

  5. sql server 缓存_了解SQL Server查询计划缓存

    sql server 缓存 Whenever a query is run for the first time in SQL Server, it is compiled and a query p ...

  6. sql查询初学者指南_面向初学者SQL Server查询执行计划–类型和选项

    sql查询初学者指南 When a DBA is working with the SQL Server, he/she might sometimes say that the execution ...

  7. Mysql与Sql Server查询数据库中表以及表字段

    1.查询数据库表信息 mysql查询数据库中所有表信息 SELECTtable_name AS '表名',table_comment AS '说明',create_time AS '创建时间',upd ...

  8. SQL Server 查询性能优化——覆盖索引(二)

    在SQL Server 查询性能优化--覆盖索引(一)  中讲了覆盖索引的一些理论. 本文将具体讲一下使用不同索引对查询性能的影响. 下面通过实例,来查看不同的索引结构,如聚集索引.非聚集索引.组合索 ...

  9. SQL Server查询所有数据库下模式schema

    SQL Server查询所有数据库下模式名 需求描述 找到SQL Server里所有数据库下的schema.输出格式为数据库名.模式名. 背景补充 关于SQL Server需要简单介绍下,从数据库对象 ...

最新文章

  1. 【Postgresql】触发器某个字段更新时执行,行插入或更新执行
  2. 单词evolve pro legacy launcher session
  3. oracle结果集过大,多重子查询/大结果集查询问题
  4. 浏览器的同源限制解决方案
  5. php微信网页授权登录代码,php微信网页授权代码(获取用户信息)
  6. Azure 国际版与中国版服务列表对(2020年6月版)
  7. 第一次使用水晶报表,柱状图的横竖坐标不会定位,怎么办?
  8. airpods pro是按压还是触摸_AirPods Pro体验:真好用,但我还是想退货啊
  9. asp.net oracle odbc,ADO.NET 连接数据库字符串小结(Oracle、SqlServer、Access、ODBC)
  10. Android 笔记 json GSON,Android中使用Gson解析JSON数据
  11. 七个习惯之七:不断更新
  12. 王阳明心学的最高境界
  13. 视频教程-计算机二级(VB)-计算机等级考试
  14. GitHub 预览 Copilot,一个 OpenAI 驱动的编码助手
  15. HTML5游戏开发高级教程 | Lynda教程 中文字幕
  16. Springboot中自定义文件映射
  17. 【论文】AlexNet 一
  18. keilU5中.lib文件的生成与调用
  19. HDU 5976 Detachment
  20. 谷粒商城十elasticsearch搜索服务及商品上架

热门文章

  1. oracle 递归查询
  2. 让CPU占用率听你指挥
  3. NET MVC3 中的枚举多语言实现,DescriptionPairAttribute
  4. 方案类:城中村社区网运营计划书-地方社区发展经典案例
  5. php 缺少参数,php - 如何验证JSON响应中是否缺少参数-Laravel 6 - 堆栈内存溢出
  6. DPDK vhost-user之前后端通知机制场景分析(十)
  7. leetcode算法题--爬楼梯
  8. flutter text 左对齐_Flutter基础篇之九-Text文本展示
  9. 电脑温度测试软件_网购电脑够便宜?坑连着坑真的不好躲
  10. Visual C++ Windows 用来定位 DLL 的搜索路径