使用SQL SERVER FOR XML PATH将多个结果集转换成一行并进行去重处理

在一个医药行业的系统中需要根据患者的接触记录ID获取不同接触类型的集合,效果像这样
 
 
--患者接触记录信息,一个患者可以有N个不同的接触记录,每个接触记录又有N个接触类型记录
IF OBJECT_ID ('dbo.TEST') IS NOT NULL
DROP TABLE dbo.TEST
GO
CREATE TABLE dbo.TEST
(
ID INT IDENTITY (1000,1) NOT NULL,
cid INT,--接触记录号
REMARK VARCHAR (4000),
CONTACTTYPE VARCHAR (20),
DESCRIBE VARCHAR (4000),
ADDDATE DATETIME
)
GO
--测试数据,包含重复类型
INSERT INTO dbo.TEST (cid, REMARK, CONTACTTYPE, DESCRIBE, ADDDATE)
VALUES (81667,'咨询备注','ContactType_1', NULL,'2014-06-03 09:53:24')
,(81667,'回访备注','ContactType_2', NULL,'2014-06-03 09:53:24')
,(81667,'咨询备注','ContactType_1', NULL,'2014-06-03 09:53:24.92')
,(81667,'回访备注','ContactType_2','回访找棕','2014-06-03 09:53:24.927')
,(81667,'随访备注','ContactType_3','随访详情','2014-06-03 09:53:24.933')
,(81667,'通知备注','ContactType_4','通知内容描述','2014-06-03 09:53:24.94')
,(81667,'预约备注','ContactType_5','预约内容','2014-06-03 09:53:24.947')
,(81667,'回复备注','ContactType_6','回复测试。。。。','2014-06-03 09:53:24.95')
,(81679,'咨询备注','ContactType_1', NULL,'2014-06-03 10:53:53.743')
,(81679,'回访备注','ContactType_2','回访内容描述','2014-06-03 10:53:53.75')
,(81679,'随访备注','ContactType_3','随访详情','2014-06-03 10:53:53.757')
,(81679,'通知备注','ContactType_4','通知内容描述','2014-06-03 10:53:53.763')
,(81679,'预约备注','ContactType_5','预约内容','2014-06-03 10:53:53.767')
,(81679,'回复备注','ContactType_6','回复内容','2014-06-03 10:53:53.777')
之前写的一个Sql方法里是这样的在正常的情况下没有问题,但如果一个接触记录存在两个相同的接触类型的话就会存在相同的接触类型(此问题有可能是代码导致的,但我并不能直接更改代码)
既然不能更改代码那只能通过数据库来处理了
--之前的sql方法,有可以会返回相同的类型则
DECLARE @SNvarchar(2000)
SET @S=''
SELECT @S=@S+'/'+(CASE ContactType
WHEN 'ContactType_1'THEN '咨询'
WHEN 'ContactType_2'THEN '回访'
WHEN 'ContactType_3'THEN '随访'
WHEN 'ContactType_4'THEN '通知'
WHEN 'ContactType_5'THEN '预约'
WHEN 'ContactType_6'THEN '回复'
END)
FROM test WHERE CID=81667
PRINT @s
以下效果显然不是我想要的
 
 
通过几个小时的努力终于通过Sql完美解决,时间全部浪费在去重的问题上
想到过的解决方法
1.在之前Sql里直接加入DISTINCT进行数据去重但一直出现错误"关键字 'DISTINCT' 附近有语法错误。 Severity 15"
2.使用临时表,先将数据查询出来并插入临时表,然后再循环临时表并添加到字符串,添加时如果存在则不会重复添加
3.先按照原来的方法得到可能重复的字符串,然后对字符串进行去重处理
4.使用我现在的方法即用for xml和DISTINCT得到已经去重的字符串然后再赋予一个变量
 
FOR XML需要SqlServer 2005+版本支持
--新的Sql方法,通过FOR XML PATH和DISTINCT进行去重处理 

DECLARE @SNvarchar(2000)
--无法在包含DISTINCT关键字的查询中将结果赋予变量,以下Sql将出现错误"关键字 'DISTINCT' 附近有语法错误。 Severity 15"
-- SELECT @s= DISTINCT -- ( '/'+(CASE ContactType -- WHEN 'ContactType_1'THEN '咨询' -- WHEN 'ContactType_2'THEN '回访' -- WHEN 'ContactType_3'THEN '随访' -- WHEN 'ContactType_4'THEN '通知' -- WHEN 'ContactType_5'THEN '预约' -- WHEN 'ContactType_6'THEN '回复' -- END) -- ) -- FROM test WHERE Cid=81667 -- FOR XML PATH('')
SELECT @S=(
SELECT DISTINCT (
'/'+(CASE ContactType
WHEN 'ContactType_1'THEN '咨询'
WHEN 'ContactType_2'THEN '回访'
WHEN 'ContactType_3'THEN '随访'
WHEN 'ContactType_4'THEN '通知'
WHEN 'ContactType_5'THEN '预约'
WHEN 'ContactType_6'THEN '回复'
END)
)
FROM test WHERE Cid=81667
FOR XML PATH('')
)
PRINT @s
通过FOR XML和DISTINCT去重后的效果
 
 
可以看到使用for xml path可以很容易的将多选结果集转换成一行
 
参考:
 
 

来自为知笔记(Wiz)



原文地址:https://www.cnblogs.com/huangtailang/p/4077168.html