--查询分组号为6的子孙子节点 with rtd1 as(select id ,pid from usergroup),rtd2 as(select * from rtd1 where id=6union allselect rtd1.* from rtd2 inner join rtd1 on rtd2.id=rtd1.pid)select * from rtd2 --现在想进一步将查询结果转换为逗号分隔的字
--查询分组号为6的子孙子节点
with rtd1 as( select id ,pid from usergroup ), rtd2 as( select * from rtd1 where id=6 union all select rtd1.* from rtd2 inner join rtd1 on rtd2.id=rtd1.pid )select * from rtd2
--现在想进一步将查询结果转换为逗号分隔的字串
--查询分组号为6的子孙子节点
with rtd1 as( select id ,pid from usergroup ), rtd2 as( select * from rtd1 where id=6 union all select rtd1.* from rtd2 inner join rtd1 on rtd2.id=rtd1.pid )--select * from rtd2select ','+cast(id as nvarchar) from rtd2 for xml path('')
查询结果如下:
,6,17,18,20,21,22,23,24,29,25,26,28,27
(13 行受影响)
--现在想进一步去掉左边逗号,同时加上左右圆括号
--查询分组号为6的子孙子节点
with rtd1 as( select id ,pid from usergroup ), rtd2 as( select * from rtd1 where id=6 union all select rtd1.* from rtd2 inner join rtd1 on rtd2.id=rtd1.pid )select '('+ stuff( (select ','+cast(id as nvarchar) from rtd2 for xml path('')),1,1,'' )+')'
查询结果如下:
(6,17,18,20,21,22,23,24,29,25,26,28,27)
(1 行受影响)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
关于以上文章中关于for xml path的用法,我贴出一位朋友的博客如下[对这位朋友表示感谢]:
for xml path 有的人可能知道有的人可能不知道,其实它就是将查询结果集以xml形式展现,有了它我们可以简化我们的查询语句实现一些以前可能需要借助函数活存储过程来完成的工作。那么以一个实例为主.
一.for xml path 简单介绍
那么还是首先来介绍一下for xml path ,假设现在有一张兴趣爱好表(hobby)用来存放兴趣爱好,表结构如下:
接下来我们来看应用for xml path的查询结果语句如下:
select * from @hobby for xml path
结果:
row>
hobbyid>1hobbyid>
hname>爬山hname>
row>
row>
hobbyid>2hobbyid>
hname>游泳hname>
row>
row>
hobbyid>3hobbyid>
hname>美食hname>
row>
由此可见for xml path 可以将查询结果根据行输出成xml各式!
那么,如何改变xml行节点的名称呢?代码如下:
select * from @hobby for xml path('myhobby')
结果一定也可想而知了吧?没错原来的行节点 变成了我们在path后面括号()中,自定义的名称,结果如下:
myhobby>
hobbyid>1hobbyid>
hname>爬山hname>
myhobby>
myhobby>
hobbyid>2hobbyid>
hname>游泳hname>
myhobby>
myhobby>
hobbyid>3hobbyid>
hname>美食hname>
myhobby>
这个时候细心的朋友一定又会问那么列节点如何改变呢?还记的给列起别名的关键字as吗?对了就是用它!代码如下:
select hobbyid as 'mycode',hname as 'myname' from @hobby for xml path('myhobby')
那么这个时候我们列的节点名称也会编程我们自定义的名称 与结果如下:
myhobby>
mycode>1mycode>
myname>爬山myname>
myhobby>
myhobby>
mycode>2mycode>
myname>游泳myname>
myhobby>
myhobby>
mycode>3mycode>
myname>美食myname>
myhobby>
噢! 既然行的节点与列的节点我们都可以自定义,我们是否可以构建我们喜欢的输出方式呢?还是看代码:
select '[ '+hname+' ]' from @hobby for xml path('')
没错我们还可以通过符号+号,来对字符串类型字段的输出格式进行定义。结果如下:
[ 爬山 ][ 游泳 ][ 美食 ]
那么其他类型的列怎么自定义? 没关系,我们将它们转换成字符串类型就行啦!例如:
select '{'+str(hobbyid)+'}','[ '+hname+' ]' from @hobby for xml path('')
好的 for xml path就基本介绍到这里吧,更多关于for xml的知识请查阅帮助文档!
接下来我们来看一个for xml path的应用场景吧!那么开始吧。。。。。。
二.一个应用场景与for xml path应用
首先呢!我们在增加一张学生表,列分别为(stuid,sname,hobby),stuid代表学生编号,sname代表学生姓名,hobby列存学生的爱好!那么现在表结构如下:
这时,我们的要求是查询学生表,显示所有学生的爱好的结果集,代码如下:
select b.sname,left(stulist,len(stulist)-1) as hobby from (
select sname,
(select hobby+',' from student
where sname=a.sname
for xml path('')) as stulist
from student a
group by sname
) b
结果如下:
分析: 好的,那么我们来分析一下,首先看这句:
select hobby+',' from student
where sname=a.sname
for xml path('')
这句是通过for xml path 将某一姓名如张三的爱好,显示成格式为:“ 爱好1,爱好2,爱好3,”的格式!
那么接着看:
select b.sname,left(stulist,len(stulist)-1) as hobby from (
select sname,
(select hobby+',' from student
where sname=a.sname
for xml path('')) as stulist
from student a
group by sname
) b
剩下的代码首先是将表分组,在执行for xml path 格式化,这时当还没有执行最外层的select时查询出的结构为:
可以看到stulist列里面的数据都会多出一个逗号,这时随外层的语句:select b.sname,left(stulist,len(stulist)-1) as hobby 就是来去掉逗号,并赋予有意义的列明!
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
关于stuff函数的用法:
删除指定长度的字符串并在指定的起始点插入另一组字符
stuff ( character_expression , start , length , character_expression )
character_expression :操作的字符,
start:删除和插入的起始点,
length:删除的长度,
character_expression :要插入的字符