--合并分拆表
/******************************************************************************************************************************************************
合并分拆表数据整理人:中国风(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 TabgoSQL2005用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>')
                )bSQL05用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'
GoSQL2000用辅助表:
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
*/

解决方案 »

  1.   

    怎么感觉不是我想要的那种效果呢?根据B表内的A_ID_Item的记录查找对应A表中的记录?双表操作。不知道是小弟功力不够没能领悟liangCK的意思了,还是liangCK米明白我想表达的含义?
      

  2.   

    declare @a table(A_Id varchar(64),A_Name varchar(64))
    insert into @a
    select '1001','aaa1'
    union all
    select '1002','aaa2'
    union all
    select '1003','aaa3'
    union all
    select '1004','aaa4'
    union all
    select '1005','aaa5'
    union all
    select '1006','aaa6'
    declare @b table(B_Id varchar(61),B_Name varchar(64),A_Id_Item varchar(64))
    insert into @b
    select '2001','bbb1','1001,1002,1003,1005'
    union all
    select '2002','bbb2','1001,1004,1006'declare @str varchar(8000)
    set @str=''
    select @str=@str+a_id_item+',' from @b
    select @str
    select A_Name from @a where charindex(a_id+',',@str)>0
      

  3.   

    楼上的大侠:
    数据类型 int 对于函数 charindex 无效。允许的类型为: char/varchar、nchar/nvarchar 和 binary/varbinary。
      

  4.   

    --> 测试数据: #T1
    if object_id('tempdb.dbo.#T1') is not null drop table #T1
    create table #T1 (A_ID int,A_Name varchar(4))
    insert into #T1
    select 1001,'aaa1' union all
    select 1002,'aaa2' union all
    select 1003,'aaa3' union all
    select 1004,'aaa4' union all
    select 1005,'aaa5' union all
    select 1006,'aaa6'
    --> 测试数据: #T2
    if object_id('tempdb.dbo.#T2') is not null drop table #T2
    create table #T2 (B_ID int,B_Name varchar(4),A_ID_Item varchar(50))
    insert into #T2
    select 2001,'bbb1','1001,1002,1003,1005' union all
    select 2002,'bbb2','1001,1004,1006'--first
    select a.*,b.B_ID,b.B_Name
    from #T1 a
     join #T2 b
       on charindex(','+ltrim(a.A_ID)+',',','+b.A_ID_Item+',')>0
       
    --second
    select top 50 id=identity(int,1,1) into # from sys.columnsselect a.*,b.B_ID,b.B_Name
    from
    (
      select a.B_ID,a.B_Name,substring(a.A_ID_Item,b.id,charindex(',',a.A_ID_Item+',',b.id)-b.id) A_ID
      from #T2 a
       join # b
         on substring(','+a.A_ID_Item,b.id,1)=','
    ) b
     join #T1 a
       on b.A_ID=a.A_ID drop table #/*
    A_ID        A_Name B_ID        B_Name
    ----------- ------ ----------- ------
    1001        aaa1   2001        bbb1
    1002        aaa2   2001        bbb1
    1003        aaa3   2001        bbb1
    1005        aaa5   2001        bbb1
    1001        aaa1   2002        bbb2
    1004        aaa4   2002        bbb2
    1006        aaa6   2002        bbb2(7 行受影响)
    */
      

  5.   

    呵呵。好强。对象名 'sys.columns' 无效。
      

  6.   


    你是2000的.
    改为syscolumns就行.