根据某一字段值相同合并字符串

作项目的过程当中,遇到一个问题,相同id,不一样value的记录但愿合并成一条记录,value以逗号分隔,从网上搜了搜解决方案,整理以下,备忘。express


1、字符串合并ide

表名:test函数

字段:spa

idint.net

namenvarchar(50)blog

字段值:字符串

指望结果:it

idnameStrio

-----------------------------class

1a,b,c

2d,e

3f

SQL实现:

一、利用函数解决

-- 建立处理函数

CREATEFUNCTION dbo.f_str(@id int)

RETURNSvarchar(8000)

AS

BEGIN

DECLARE @r varchar(8000)

SET @r =''

SELECT @r = @r +','+ [name]

FROM [test]

WHERE [id]=@id

SET @r =STUFF(@r, 1, 1,'')

RETURN @r

END


GO


-- 调用函数

SELECT [id], [nameStr]=dbo.f_str(id)

FROM [test]

GROUPBY [id]

运行结果:


二、直接用SQL解决

SELECT*

FROM(

SELECTDISTINCT [id]

FROM [test]

)A

OUTERAPPLY(

SELECT

[nameStr]=STUFF(REPLACE(REPLACE(

(

SELECT [name] FROM [test] N

WHERE [id] = A.id

FORXMLAUTO

),'<N name="',','),'"/>',''), 1, 1,'')

)M

运行结果:


看不懂这个SQL没关系,下面有详细分析

2、详细分析

一、STUFF

做用:

STUFF函数将字符串插入另外一字符串。它在第一个字符串中从开始位置删

除指定长度的字符;而后将第二个字符串插入第一个字符串的开始位置。

语法:

       STUFF ( character_expression , start , length ,character_expression )

参数:

character_expression

一个字符数据表达式。character_expression能够是常量、变量,也可

以是字符列或二进制数据列。

start

一个整数值,指定删除和插入的开始位置。若是startlength为负,

     则返回空字符串。若是start比第一个character_expression长,则返

     回空字符串。start能够是bigint类型。

length

一个整数,指定要删除的字符数。若是length比第一个

character_expression长,则最多删除到第一个character_expression

中的最后一个字符。Length能够是bigint类型。

返回类型:

若是character_expression是受支持的字符数据类型,则返回字符数据。

若是character_expression是一个受支持的 binary 数据类型,则返回二

进制数据。

注释:

  若是开始位置或长度值是负数,或者若是开始位置大于第一个字符串的长

度,将返回空字符串。若是要删除的长度大于第一个字符串的长度,将删

除到第一个字符串中的最后一个字符。若是结果值大于返回类型支持的最

大值,则产生错误。

示例:

SELECTSTUFF('abcdef', 2, 3,'ijklmn');

GO

结果:

SELECTSTUFF('abcdef',-2, 3,'ijklmn');

GO

结果:

SELECTSTUFF('abcdef', 2, 10,'ijklmn');

GO

结果:

二、CROSS APPLY OUTERAPPLY

使用 APPLY 运算符能够为实现查询操做的外部表表达式返回的每一个行调用表值函数。表值函数做为右输入,外部表表达式做为左输入。经过对右输入求值来得到左输入每一行的计算结果,生成的行被组合起来做为最终输出。APPLY 运算符生成的列的列表是左输入中的列集,后跟右输入返回的列的列表。

APPLY 有两种形式:CROSS APPLY OUTER APPLYCROSS APPLY 仅返回外部表中经过表值函数生成结果集的行。OUTER APPLY 既返回生成结果集的行,也返回不生成结果集的行,其中表值函数生成的列中的值为 NULL

用示例来区分二者:

第一张表:

表名:student

字段名:

字段值:

第二张表:

表名:student_class

字段名:

字段值:

CROSS APPLY

SELECT*

FROM [student] a

CROSSAPPLY(

SELECT [class], [score]

FROM [student_class]

WHERE student_id = a.id

) b


运行结果:



OUTERAPPLY

SELECT*

FROM [student] a

OUTERAPPLY(

SELECT [class], [score]

FROM [student_class]

WHERE student_id = a.id

) b

运行结果:

三、FORXMLAUTO

将结果转换为XML结构,例如对于上面2中的student表,执行如下语句

SELECT*

FROM [student]

FORXMLAUTO


运行结果:


其中FOR XML还有其余方式:RAWEXPLICITPATH,有兴趣的同窗能够深刻研究,这里再也不赘述。


转载至:http://blog.csdn.net/xiaomianao2010/article/details/6035634

相关文章
相关标签/搜索