背景

经常有需求将一条记录对于的几条记录,在一行内显示。比如张三的技术有计算机和英语,要求显示为张三 计算机,英语。如下表:
源数据:

张三 计算机
张三 英语

要求:

张三 计算机,英语

这里如果使用循环或者游标都可以处理,但是比较麻烦,效率比较底。可以使用for xml 提示和stuff结合来处理这类问题。

实例:

  1. /*  
  2. 问题:  
  3. 表A 字段ID(int),ClassId(nvarchar(50))  
  4.  
  5. 表B 字段ID(int),ClassName(nvarchar(50))  
  6.  
  7. 表A的ClassId是一个列表用逗号分割的,例如“1,2,3,4,6,8”,对应的是表B的ID字段  
  8.  
  9. 有没有什么办法用一条语句查询出表A,并且把表A的ClassId字段中的数字替换成表B中对应ID的ClassName  
  10. */  
  11. create table #tableA   
  12. (  
  13.     id int,  
  14.     classid varchar(20)  
  15. )  
  16. create table  #tableB   
  17. (  
  18.     id int,  
  19.     className varchar(20)  
  20. )  
  21. insert into #tableA select 1,'1,2,3,4,5,6' 
  22. insert into #tableB select 1,'类别1' union all   
  23. select 2,'类别2' union all   
  24. select 3,'类别3' union all   
  25. select 4,'类别4' union all   
  26. select 5,'类别5' union all   
  27. select 6,'类别6'   
  28. go  
  29. --测试代码  
  30. declare @sql nvarchar(2000)  
  31. --select @sql='select * from #tableB where id in ('+classid+')' from #tableA  
  32. select @sql='select stuff((select '',''+classname from #tableB where id in ('+classid+') for xml path('''')),1,1,'''')' from #tableA  
  33. print @sql  
  34. --实际生成的sql  
  35. --select stuff((select ','+classname from #tableB where id in (1,2,3,4,5,6) for xml path('')),1,1,'')  
  36. exec(@sql)  
  37. --这个例子,只能用动态sql的方式来处理这个要求,稍微扩展一下就可以达到目的。  
  38. /*  
  39. --结果  
  40. ------------------------------------  
  41. 类别1,类别2,类别3,类别4,类别5,类别6  
  42. (1 行受影响)  
  43. */