CSDN-CSDN社区-MS-SQL Server-应用实例

收藏 [推荐] 合并分拆表_整理贴1[问题点数:120,结帖人:roy_88]

  • roy_88
  • (中国风)
  • 等 级:
  • 结帖率:
  • 2

    4

楼主发表于:2008-06-12 22:33:01
SQL code
--合并分拆表 /****************************************************************************************************************************************************** 合并分拆表数据 整理人:中国风(Roy) 日期:2008.06.06 ******************************************************************************************************************************************************/ --> --> (Roy)生成測試數據 if not object_id('Tab') is null drop table Tab Go Create table Tab([Col1] int,[Col2] nvarchar(1)) Insert Tab select 1,N'a' union all select 1,N'b' union all select 1,N'c' union all select 2,N'd' union all select 2,N'e' union all select 3,N'f' Go 合并表: SQL2000用函数: go if object_id('F_Str') is not null drop function F_Str go create function F_Str(@Col1 int) returns nvarchar(100) as begin declare @S nvarchar(100) select @S=isnull(@S+',','')+Col2 from Tab where Col1=@Col1 return @S end go Select distinct Col1,Col2=dbo.F_Str(Col1) from Tab go SQL2005用XML: 方法1: select a.Col1,Col2=stuff(b.Col2.value('/R[1]','nvarchar(max)'),1,1,'') from (select distinct COl1 from Tab) a Cross apply (select COl2=(select N','+Col2 from Tab where Col1=a.COl1 For XML PATH(''), ROOT('R'), TYPE))b 方法2: select a.Col1,COl2=replace(b.Col2.value('/Tab[1]','nvarchar(max)'),char(44)+char(32),char(44)) from (select distinct COl1 from Tab) a cross apply (select Col2=(select COl2 from Tab where COl1=a.COl1 FOR XML AUTO, TYPE) .query('<Tab> {for $i in /Tab[position()<last()]/@COl2 return concat(string($i),",")} {concat("",string(/Tab[last()]/@COl2))} </Tab>') )b SQL05用CTE: ;with roy as(select Col1,Col2,row=row_number()over(partition by COl1 order by COl1) from Tab) ,Roy2 as (select COl1,cast(COl2 as nvarchar(100))COl2,row from Roy where row=1 union all 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) select Col1,Col2 from Roy2 a where row=(select max(row) from roy where Col1=a.COl1) order by Col1 option (MAXRECURSION 0) 生成结果: /* Col1 COl2 ----------- ------------ 1 a,b,c 2 d,e 3 f (3 行受影响) */ 拆分表: --> --> (Roy)生成測試數據 if not object_id('Tab') is null drop table Tab Go Create table Tab([Col1] int,[COl2] nvarchar(5)) Insert Tab select 1,N'a,b,c' union all select 2,N'd,e' union all select 3,N'f' Go SQL2000用辅助表: if object_id('Tempdb..#Num') is not null drop table #Num go select top 100 ID=Identity(int,1,1) into #Num from syscolumns a,syscolumns b Select a.Col1,COl2=substring(a.Col2,b.ID,charindex(',',a.Col2+',',b.ID)-b.ID) from Tab a,#Num b where charindex(',',','+a.Col2,b.ID)=b.ID --也可用 substring(','+a.COl2,b.ID,1)=',' SQL2005用Xml: select a.COl1,b.Col2 from (select Col1,COl2=convert(xml,'<root><v>'+replace(COl2,',','</v><v>')+'</v></root>') from Tab)a outer apply (select Col2=C.v.value('.','nvarchar(100)') from a.COl2.nodes('/root/v')C(v))b SQL05用CTE: ;with roy as (select Col1,COl2=cast(left(Col2,charindex(',',Col2+',')-1) as nvarchar(100)),Split=cast(stuff(COl2+',',1,charindex(',',Col2+','),'') as nvarchar(100)) from Tab union all 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>'' ) select COl1,COl2 from roy order by COl1 option (MAXRECURSION 0) 生成结果: /* Col1 COl2 ----------- ----- 1 a 1 b 1 c 2 d 2 e 3 f */
回复次数:110
  • liangCK用户头像
  • liangCK
  • (小梁 爱 兰儿 (梁爱兰))
  • 等 级:
  • 2

    2

#1楼 得分:5回复于:2008-06-12 22:33:50
支持,接分.
#2楼 得分:5回复于:2008-06-12 22:34:59
学习
#3楼 得分:2回复于:2008-06-12 22:35:54
深深的敬礼
#4楼 得分:2回复于:2008-06-12 22:43:54
上午就见一帖整理  学习
  • yiyi_wx用户头像
  • yiyi_wx
  • (依依(塞翁失马焉知非福))
  • 等 级:
#5楼 得分:2回复于:2008-06-12 22:50:23
引用 3 楼 happyflystone 的回复:
深深的敬礼
  • fcuandy用户头像
  • fcuandy
  • (顾湘云)
  • 等 级:
  • 3

#6楼 得分:2回复于:2008-06-12 22:51:34
sf
#7楼 得分:2回复于:2008-06-12 22:55:51
引用 2 楼 happyflystone 的回复:
学习

引用 3 楼 happyflystone 的回复:
深深的敬礼
#8楼 得分:2回复于:2008-06-12 22:56:05
谢谢 收下了
#9楼 得分:2回复于:2008-06-12 22:56:59
引用 1 楼 liangCK 的回复:
支持,接分.


引用 4 楼 wzy_love_sly 的回复:
上午就见一帖整理  学习

引用 6 楼 fcuandy 的回复:
sf
  • ws_hgo用户头像
  • ws_hgo
  • (蓝天白云--(全面提升!!))
  • 等 级:
#10楼 得分:2回复于:2008-06-12 23:03:38
谢谢
LZ
收藏了
  • roy_88用户头像
  • roy_88
  • (中国风)
  • 等 级:
  • 2

    4

#11楼 得分:0回复于:2008-06-12 23:36:13
引用 4 楼 wzy_love_sly 的回复:
上午就见一帖整理  学习


哈哈~~~
端午节期间闲来没事,整理几篇。。。
整合大家的思想+自己的想法

该回复于2008-06-12 23:36:45被版主修改

  • pt1314917用户头像
  • pt1314917
  • (背着灵魂漫步)
  • 等 级:
#12楼 得分:2回复于:2008-06-13 08:53:09
挺不错的。。学习``
#13楼 得分:2回复于:2008-06-13 08:55:27
感觉第一个应该变下效率会更高吧 。

select col1,Col2=dbo.F_Str(Col1) from (
Select distinct Col1 from Tab ) t

这样函数就不会执行那么多次了。不知道是否有理?

接分来了,哈哈!
  • Herb2用户头像
  • Herb2
  • (二等草)
  • 等 级:
#14楼 得分:2回复于:2008-06-13 08:55:31
引用 12 楼 pt1314917 的回复:
挺不错的。。学习``
#15楼 得分:2回复于:2008-06-13 08:57:22
引用 11 楼 roy_88 的回复:
引用 4 楼 wzy_love_sly 的回复:
上午就见一帖整理  学习
哈哈~~~
端午节期间闲来没事,整理几篇。。。
整合大家的思想+自己的想法


支持++
  • fa_ge用户头像
  • fa_ge
  • (鶴嘯九天)
  • 等 级:
#16楼 得分:2回复于:2008-06-13 08:58:13
引用 12 楼 pt1314917 的回复:
挺不错的。。学习``
#17楼 得分:2回复于:2008-06-13 09:03:58

[color=#FF0000]收了,拿来赚分 ~~[/color]
#18楼 得分:2回复于:2008-06-13 09:10:47
引用 12 楼 pt1314917 的回复:
挺不错的。。学习``
#19楼 得分:2回复于:2008-06-13 09:15:09
下面是我整理的:
SQL code
-- ============================================================================= -- Title: 在SQL中分类合并数据行 -- Author: dobear Mail(MSN): dobear_0922@hotmail.com -- Environment: Vista + SQL2005 -- Date: 2008-04-22 -- ============================================================================= --1. 创建表,添加测试数据 CREATE TABLE tb(id int, [value] varchar(10)) INSERT tb SELECT 1, 'aa' UNION ALL SELECT 1, 'bb' UNION ALL SELECT 2, 'aaa' UNION ALL SELECT 2, 'bbb' UNION ALL SELECT 2, 'ccc' --SELECT * FROM tb /**//* id value ----------- ---------- 1 aa 1 bb 2 aaa 2 bbb 2 ccc (5 row(s) affected) */ --2 在SQL2000只能用自定义函数实现 ----2.1 创建合并函数fn_strSum,根据id合并value值 GO CREATE FUNCTION dbo.fn_strSum(@id int) RETURNS varchar(8000) AS BEGIN DECLARE @values varchar(8000) SET @values = '' SELECT @values = @values + ',' + value FROM tb WHERE id=@id RETURN STUFF(@values, 1, 1, '') END GO -- 调用函数 SELECT id, VALUE = dbo.fn_strSum(id) FROM tb GROUP BY id DROP FUNCTION dbo.fn_strSum ----2.2 创建合并函数fn_strSum2,根据id合并value值 GO CREATE FUNCTION dbo.fn_strSum2(@id int) RETURNS varchar(8000) AS BEGIN DECLARE @values varchar(8000) SELECT @values = isnull(@values + ',', '') + value FROM tb WHERE id=@id RETURN @values END GO -- 调用函数 SELECT id, VALUE = dbo.fn_strSum2(id) FROM tb GROUP BY id DROP FUNCTION dbo.fn_strSum2 --3 在SQL2005中的新解法 ----3.1 使用OUTER APPLY SELECT * FROM (SELECT DISTINCT id FROM tb) A OUTER APPLY( SELECT [values]= STUFF(REPLACE(REPLACE( ( SELECT value FROM tb N WHERE id = A.id FOR XML AUTO ), '<N value="', ','), '"/>', ''), 1, 1, '') )N ----3.2 使用XML SELECT id, [values]=STUFF((SELECT ','+[value] FROM tb t WHERE id=tb.id FOR XML PATH('')), 1, 1, '') FROM tb GROUP BY id --4 删除测试表tb drop table tb /**//* id values ----------- -------------------- 1 aa,bb 2 aaa,bbb,ccc (2 row(s) affected) */
#20楼 得分:2回复于:2008-06-13 09:16:07
  • sweetweiwei用户头像
  • sweetweiwei
  • ((薇薇)世上本无事,庸人自扰之)
  • 等 级:
#21楼 得分:2回复于:2008-06-13 09:20:35
学习
  • roy_88用户头像
  • roy_88
  • (中国风)
  • 等 级:
  • 2

    4

#22楼 得分:0回复于:2008-06-13 10:31:18
引用 13 楼 hanjs 的回复:
感觉第一个应该变下效率会更高吧 。

select col1,Col2=dbo.F_Str(Col1) from (
Select distinct Col1 from Tab ) t

这样函数就不会执行那么多次了。不知道是否有理?

接分来了,哈哈!


以上只是要顯示結果。。
效率用group by col1就行了,不用嵌套
  • Sandy945用户头像
  • Sandy945
  • (阿非 (艰难困苦,玉汝于成!))
  • 等 级:
#23楼 得分:2回复于:2008-06-13 11:26:01
学习 ~
  • sp4用户头像
  • sp4
  • (擅打迷踪拳)
  • 等 级:
#24楼 得分:2回复于:2008-06-13 11:52:17
例子而已,不需要深究。
一个解决问题不错方法.......
#25楼 得分:2回复于:2008-06-13 12:15:14
学习!
#26楼 得分:2回复于:2008-06-13 12:45:49
学习!
#27楼 得分:2回复于:2008-06-13 12:46:20
接分,学习!
#28楼 得分:2回复于:2008-06-13 12:53:02
学习.
  • xiaoku用户头像
  • xiaoku
  • (野蛮人(^v^))
  • 等 级:
#29楼 得分:2回复于:2008-06-13 12:59:51
悟空,看看。。。
  • liuqian4243用户头像
  • liuqian4243
  • (新工作,新开始呀!为世界奋斗着)
  • 等 级:
#30楼 得分:2回复于:2008-06-13 13:11:05
引用 3 楼 happyflystone 的回复:
深深的敬礼


看看。。。
#31楼 得分:1回复于:2008-06-13 13:14:06
支持一下
  • diablososi用户头像
  • diablososi
  • (给我一口油井,我来给地球制造高)
  • 等 级:
#32楼 得分:1回复于:2008-06-13 14:21:18
ding
  • diablososi用户头像
  • diablososi
  • (给我一口油井,我来给地球制造高)
  • 等 级:
#33楼 得分:1回复于:2008-06-13 14:21:32
jf
  • diablososi用户头像
  • diablososi
  • (给我一口油井,我来给地球制造高)
  • 等 级:
#34楼 得分:1回复于:2008-06-13 14:21:43
jf
  • xp1056用户头像
  • xp1056
  • (男人,要对自己残忍一点)
  • 等 级:
#35楼 得分:1回复于:2008-06-13 14:25:06
UP
  • HEROWANG用户头像
  • HEROWANG
  • (让你望见影子的墙)
  • 等 级:
#36楼 得分:3回复于:2008-06-13 14:30:54
自已以前写的:
SQL code
使用的是游标和循环截取法 declare @tb table(id int identity(1,1),name char(50)) insert @tb select'jame,job' insert @tb select 'carl,mc' insert @tb select 'paul' declare c1 cursor for select name from @tb declare @tmp table(id int identity(1,1),name char(50)) declare @s char(50) open c1 fetch c1 into @s while(@@fetch_status = 0) begin while charindex(',',@s)>0 begin insert into @tmp values(left(@s,charindex(',',@s)-1)) set @s=stuff(@s,1,charindex(',',@s),'') end INSERT @tmp VALUES(@s) fetch next from c1 into @s end select * from @tmp close c1 deallocate c1 动态sql法 declare @tb table(id int identity(1,1),name char(50)) insert @tb select'jame,job' insert @tb select 'carl,mc' insert @tb select 'paul' declare c1 cursor for select name from @tb declare @s char(50) declare @sql char(8000) open c1 fetch c1 into @s while(@@fetch_status = 0) begin set @sql='select '''+replace(@s,',',''' union all select ''')+'''' insert tmp exec(@sql) fetch next from c1 into @s end select * from tmp close c1 deallocate c1


http://topic.csdn.net/u/20080510/13/8ca706fd-3c13-417a-ace8-6ec2a0cd182a.html
上面还有小楼写的几种方法
  • skyzcl用户头像
  • skyzcl
  • (小飞)
  • 等 级:
#37楼 得分:1回复于:2008-06-13 14:32:29
mark
  • zhou968用户头像
  • zhou968
  • (☆子灵☆)
  • 等 级:
#38楼 得分:1回复于:2008-06-13 14:37:00
引用 1 楼 liangCK 的回复:
支持,接分.
#39楼 得分:1回复于:2008-06-13 14:48:05
mark
  • zhou968用户头像
  • zhou968
  • (☆子灵☆)
  • 等 级:
#40楼 得分:1回复于:2008-06-13 14:54:58
引用 38 楼 zhou968 的回复:
引用 1 楼 liangCK 的回复:
支持,接分.
#41楼 得分:1回复于:2008-06-13 20:52:20
引用 5 楼 yiyi_wx 的回复:
引用 3 楼 happyflystone 的回复:
深深的敬礼
#42楼 得分:1回复于:2008-06-13 21:34:55
堪称经典
#43楼 得分:1回复于:2008-06-14 05:41:44
谢谢LZ,收藏了
  • hery2002用户头像
  • hery2002
  • (苦*行*僧)
  • 等 级:
  • 2

    2

#44楼 得分:1回复于:2008-06-14 08:06:10
顶风
只是不敢作案.
^_^
#45楼 得分:1回复于:2008-06-14 10:38:49
学习~
#46楼 得分:1回复于:2008-06-14 11:45:08
学习,备用!
  • auqfiudh用户头像
  • auqfiudh
  • (才发现自己啥都不懂.)
  • 等 级:
#47楼 得分:1回复于:2008-06-14 16:55:36
引用 1 楼 liangCK 的回复:
支持,接分.
  • RoverX用户头像
  • RoverX
  • (请输入你的社区昵称)
  • 等 级:
#48楼 得分:1回复于:2008-06-14 18:24:20
学习,向楼主学习
  • wzjpsq用户头像
  • wzjpsq
  • (北伐)
  • 等 级:
#49楼 得分:1回复于:2008-06-14 22:06:26
MARK
相关问题
拆分一个被分隔符隔开的字段
一个数据查询合并删除问题!
字符串合并的问题
苦*行*僧帮个忙呀?谢谢!
sql 分组查询中每组中某列的各行字符数据相加显示
合并数据字段的问题,上次的问题已给分,希望高手继续帮忙解答