SQL中合并分拆表方法汇总

  dobear_0922 兄弟整理的方法如下:
  1. -- =============================================================================
  2. -- Title: 在SQL中分类合并数据行
  3. -- Author: dobear        Mail(MSN): dobear_0922@hotmail.com
  4. -- Environment: Vista + SQL2005
  5. -- Date: 2008-04-22
  6. -- =============================================================================
  7. --1. 创建表,添加测试数据
  8. CREATE TABLE tb(id int, [value] varchar(10))
  9. INSERT tb SELECT 1, 'aa'
  10. UNION ALL SELECT 1, 'bb'
  11. UNION ALL SELECT 2, 'aaa'
  12. UNION ALL SELECT 2, 'bbb'
  13. UNION ALL SELECT 2, 'ccc'
  14. --SELECT * FROM tb
  15. /**//*
  16. id          value
  17. ----------- ----------
  18. 1           aa
  19. 1           bb
  20. 2           aaa
  21. 2           bbb
  22. 2           ccc
  23. (5 row(s) affected)
  24. */
  25. --2 在SQL2000只能用自定义函数实现
  26. ----2.1 创建合并函数fn_strSum,根据id合并value值
  27. GO
  28. CREATE FUNCTION dbo.fn_strSum(@id int)
  29. RETURNS varchar(8000)
  30. AS
  31. BEGIN
  32.     DECLARE @values varchar(8000)
  33.     SET @values = ''
  34.     SELECT @values = @values + ',' + value FROM tb WHERE id=@id
  35.     RETURN STUFF(@values, 1, 1, '')
  36. END
  37. GO
  38. -- 调用函数
  39. SELECT id, VALUE = dbo.fn_strSum(id) FROM tb GROUP BY id
  40. DROP FUNCTION dbo.fn_strSum
  41. ----2.2 创建合并函数fn_strSum2,根据id合并value值
  42. GO
  43. CREATE FUNCTION dbo.fn_strSum2(@id int)
  44. RETURNS varchar(8000)
  45. AS
  46. BEGIN
  47.     DECLARE @values varchar(8000)    
  48.     SELECT @values = isnull(@values + ',''') + value FROM tb WHERE id=@id
  49.     RETURN @values
  50. END
  51. GO
  52. -- 调用函数
  53. SELECT id, VALUE = dbo.fn_strSum2(id) FROM tb GROUP BY id
  54. DROP FUNCTION dbo.fn_strSum2
  55. --3 在SQL2005中的新解法
  56. ----3.1 使用OUTER APPLY
  57. SELECT * 
  58. FROM (SELECT DISTINCT id FROM tb) A OUTER APPLY(
  59.         SELECT [values]= STUFF(REPLACE(REPLACE(
  60.             (
  61.                 SELECT value FROM tb N
  62.                 WHERE id = A.id
  63.                 FOR XML AUTO
  64.             ), '<N value="'','), '"/>'''), 1, 1, '')
  65. )N
  66. ----3.2 使用XML
  67. SELECT id, [values]=STUFF((SELECT ','+[value] FROM tb t WHERE id=tb.id FOR XML PATH('')), 1, 1, '')
  68. FROM tb
  69. GROUP BY id
  70. --4 删除测试表tb
  71. drop table tb
  72. /**//*
  73. id          values
  74. ----------- --------------------
  75. 1           aa,bb
  76. 2           aaa,bbb,ccc
  77. (2 row(s) affected)
  78. */

 

roy_88 兄弟整理的方法:

  1. --合并分拆表
  2. /******************************************************************************************************************************************************
  3. 合并分拆表数据
  4. 整理人:中国风(Roy)
  5. 日期:2008.06.06
  6. ******************************************************************************************************************************************************/
  7. --> --> (Roy)生成測試數據
  8. if not object_id('Tab'is null
  9.     drop table Tab
  10. Go
  11. Create table Tab([Col1] int,[Col2] nvarchar(1))
  12. Insert Tab
  13. select 1,N'a' union all
  14. select 1,N'b' union all
  15. select 1,N'c' union all
  16. select 2,N'd' union all
  17. select 2,N'e' union all
  18. select 3,N'f'
  19. Go
  20. 合并表:
  21. SQL2000用函数:
  22. go
  23. if object_id('F_Str'is not null
  24.     drop function F_Str
  25. go
  26. create function F_Str(@Col1 int)
  27. returns nvarchar(100)
  28. as
  29. begin
  30.     declare @S nvarchar(100)
  31.     select @S=isnull(@S+',','')+Col2 from Tab where Col1=@Col1
  32.     return @S
  33. end
  34. go
  35. Select distinct Col1,Col2=dbo.F_Str(Col1) from Tab
  36. go
  37. SQL2005用XML:
  38. 方法1:
  39. select 
  40.     a.Col1,Col2=stuff(b.Col2.value('/R[1]','nvarchar(max)'),1,1,'')
  41. from 
  42.     (select distinct COl1 from Tab) a
  43. Cross apply
  44.     (select COl2=(select N','+Col2 from Tab where Col1=a.COl1 For XML PATH(''), ROOT('R'), TYPE))b
  45. 方法2:
  46. select 
  47.     a.Col1,COl2=replace(b.Col2.value('/Tab[1]','nvarchar(max)'),char(44)+char(32),char(44))
  48. from 
  49.     (select distinct COl1 from Tab) a
  50. cross apply
  51.     (select Col2=(select COl2 from Tab  where COl1=a.COl1 FOR XML AUTO, TYPE)
  52.                 .query('<Tab>
  53.                 {for $i in /Tab[position()<last()]/@COl2 return concat(string($i),",")}
  54.                 {concat("",string(/Tab[last()]/@COl2))}
  55.                 </Tab>')
  56.                 )b
  57. SQL05用CTE:
  58. ;with roy as(select Col1,Col2,row=row_number()over(partition by COl1 order by COl1) from Tab)
  59. ,Roy2 as
  60. (select COl1,cast(COl2 as nvarchar(100))COl2,row from Roy where row=1 
  61. union all 
  62. select a.Col1,cast(b.COl2+','+a.COl2 as nvarchar(100)),a.row from Roy a join Roy2 b on a.COl1=b.COl1 and a.row=b.row+1)
  63. select Col1,Col2 from Roy2 a where row=(select max(row) from roy where Col1=a.COl1) order by Col1 option (MAXRECURSION 0)
  64. 生成结果:
  65. /*
  66. Col1        COl2
  67. ----------- ------------
  68. 1           a,b,c
  69. 2           d,e
  70. 3           f
  71. (3 行受影响)
  72. */
  73. 拆分表:
  74. --> --> (Roy)生成測試數據
  75. if not object_id('Tab'is null
  76.     drop table Tab
  77. Go
  78. Create table Tab([Col1] int,[COl2] nvarchar(5))
  79. Insert Tab
  80. select 1,N'a,b,c' union all
  81. select 2,N'd,e' union all
  82. select 3,N'f'
  83. Go
  84. SQL2000用辅助表:
  85. if object_id('Tempdb..#Num'is not null
  86.     drop table #Num
  87. go
  88. select top 100 ID=Identity(int,1,1) into #Num from syscolumns a,syscolumns b
  89. Select 
  90.     a.Col1,COl2=substring(a.Col2,b.ID,charindex(',',a.Col2+',',b.ID)-b.ID) 
  91. from 
  92.     Tab a,#Num b
  93. where
  94.     charindex(',',','+a.Col2,b.ID)=b.ID --也可用 substring(','+a.COl2,b.ID,1)=','
  95. SQL2005用Xml:
  96. select 
  97.     a.COl1,b.Col2
  98. from 
  99.     (select Col1,COl2=convert(xml,'<root><v>'+replace(COl2,',','</v><v>')+'</v></root>') from Tab)a
  100. outer apply
  101.     (select Col2=C.v.value('.','nvarchar(100)') from a.COl2.nodes('/root/v')C(v))b
  102. SQL05用CTE:
  103. ;with roy as 
  104. (select Col1,COl2=cast(left(Col2,charindex(',',Col2+',')-1) as nvarchar(100)),Split=cast(stuff(COl2+',',1,charindex(',',Col2+','),''as nvarchar(100)) from Tab
  105. union all
  106. select Col1,COl2=cast(left(Split,charindex(',',Split)-1) as nvarchar(100)),Split= cast(stuff(Split,1,charindex(',',Split),''as nvarchar(100)) from Roy where split>''
  107. )
  108. select COl1,COl2 from roy order by COl1 option (MAXRECURSION 0)
  109. 生成结果:
  110. /*
  111. Col1        COl2
  112. ----------- -----
  113. 1           a
  114. 1           b
  115. 1           c
  116. 2           d
  117. 2           e
  118. 3           f
  119. */

更多方法

http://topic.csdn.net/u/20080612/22/c850499f-bce3-4877-82d5-af2357857872.html

http://topic.csdn.net/u/20080510/13/8ca706fd-3c13-417a-ace8-6ec2a0cd182a.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值