1,创建表,然后开始一步一步的进行,
CREATE TABLE [dbo].[Student](
[sid] [int] IDENTITY(1,1) NOT NULL,
[name] [nvarchar](50) NULL,
[age] [int] NULL,
CONSTRAINT [PK_Student] PRIMARY KEY CLUSTERED
(
[sid] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
表中数据如下
接下来,就是我们常用的一个情景,根据年龄(age)分组,得出每个组中的人(name)
正常情况下,把age 和 name 都作为了分组条件箱结果肯定就不理想了,那么如果将name作为一列能显示同时不用分组就很ok了
那些这里用到 for xml path ,这是什么呢?
一步步看效果:
然后表中数据可以看到一个xml,就是这样的:
说白了,就是把表数据都变成了xml格式都对象集,关键显示还是一行一列,对于子查询是很友好哒
接下来就好说了,我们可以把分组条件作为 这个xml 的 条件,不就可以在一列中查出xml多个符合条件都节点了吗,也就是多个数据。
上代码就是这样的:
这样是达到了,我们想要的,但是数据不太规范,当然也可以读取在程序中自己去处理,这里用sql处理一下,
1, for xml path (‘’) 去掉row标签,也可以用别的字符,那么row就变来,
2,列名+拼接可以直接去掉 列名标签
给个例子:
select
age 年龄,
(
select ','+name from Student a where a.age=b.age for xml path('')
)
as 名字
from Student b
group by age
结果如下
效果好了很多,这时候再处理下, 分隔用的逗号,可以使用 left 或者 stuff
这里用stuff 处理
stuff (<character_expression>,<开始>,<长度>,<character_expression>)
<character_expression>参数是给定的字符串数据,可以是字符或二进制,
简单来说,就是在一串字符(第一个参数)的指定位置(第二个参数)替换上多少长度(第三个参数)的特定字符(第四个参数)
举个例子:
DECLARE @aa VARCHAR(10)='abc'
SELECT STUFF(@aa, 1, 2, 'D')
SELECT STUFF(@aa, 1, 2, 'D') 中的意思:1是起始位置,就是字符串中的a。 2是两个长度,从a算起就是指的ab字符了,'D'替换的字符;
根据这个,把我们的前面的逗号去掉就好了,细心的家伙,应该发现了,前面都sql为什么不把逗号放到后面了,因为这个只有放在最前面的时候,运用stuff才确定长度和开始位置都是1,不然处理不了的
上结果:
select age 年龄,
stuff( ( select ','+ name from Student a where a.age=b.age for xml path('') ) ,1,1,'')
as 名字
from Student b
group by age
扩展下,将名字这列里面的数据全部显示出来,显示为json的格式
select age as 年纪 ,
'['+
stuff(
(
select ','+ '{'+ '"name":'+ convert(nvarchar(10),'"'+name+'"')+','+ '"sid":'+convert(nvarchar(10),sid)+'}'
from Student a where a.age=b.age for xml path('')
) ,1,1,'')
+']' as 名字
from Student b
group by age
校验:
暂时写到这,欢迎指教!