前幾天老大發來需求,是要出個報表來着。嗯,就是一行變多行。
來貼個簡單的需求:
現有如下表格
要求變成如下:
ok,因為有逗號,我首先想到的就是想辦法把逗號去掉。結果發現sql沒有提供像C#那樣split的方法,所以就自己寫了個如下:

/****** Object: UserDefinedFunction [dbo].[mysplit] Script Date: 09/19/2012 16:52:32 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO create FUNCTION [dbo].[mysplit]--將以某分隔符分段的字串,按指定的順序號提取子串 (@str nvarchar(2000),--源字串 @sn int, --提取序號 @Deli varchar(1) --分隔符 ) RETURNS varchar(100) AS BEGIN declare @first int,@last int,@result varchar(1000),@sn0 int select @sn0=0,@first=0,@LAST=1,@str=@str+REPLICATE(@DELI,1) while @sn0!=@sn begin select @sn0=@sn0+1,@first=@LAST,@last=charindex(@DELI,@str,@LAST)+1 end if @last-@first-1<0 set @result='' else SET @RESULT=SUBSTRING(@str,@FIRST,@LAST-@FIRST-1) RETURN ( @RESULT ) END GO
有了分開的方法,我就有了左連的想法:

1 if exists (select * from sysobjects where name='Cut') 2 drop proc Cut1 3 go 4 create proc Cut1 5 as 6 SELECT id,dbo.mysplit(txt,1,',') AS txt,1 AS SN from PkTable 7 union 8 SELECT id,dbo.mysplit(txt,2,',') AS txt,1 AS SN from PKTable 9 union 10 SELECT id,dbo.mysplit(txt,2,',') AS txt,1 AS SN from PKTablee 11 ORDER BY id,txt,sn 12 go 13 14 exec Cut1
結果是出來了,但是確是有不少空白字段的。大家可以試一下,這里就不再多說了
查查資料啊,各種問啊。終於尋到一個很神奇的辦法哈

1 select 2 a.id,b.txt 3 from 4 (select id,txt=convert(xml,'<root><v>'+replace(txt,',','</v><v>')+'</v></root>') from PkTable)a 5 outer apply 6 (select txt=C.v.value('.','nvarchar(100)') from a.txt.nodes('/root/v')C(v))b
OK 很成功!代碼簡潔 功能實現!
是的,哥們兒。我這里用到了sql xml
我用節點符號替換了逗號,然后用 C.V.value通過節點把他分離顯示
來來,大家討論下,第一次用,不是太熟,多多指教。
編輯上博友的好方法 供大家參考:
可以用:CTE
效率比 XML法快
1 with T (id,P1,P2) as 2 ( 3 select id,charindex(',',','+name),charindex(',',name+',')+1from #T 4 unionall 5 select a.id,b.P2,charindex(',',name+',',b.P2)+1from #T a join T b on a.id=b.id where charindex(',',name+',',b.P2)>0 6 ) 7 select a.id,name=substring(a.name+',',b.P1,b.P2 - b.P1 -1) from #T a join T b on a.id=b.id orderby1