简体   繁体   中英

SQL Server 2005: How to split a stacked column with unknown number of splits

I am having more issues with splitting stacked columns, and would love some help to complete this last part. I was trying to apply another solution I had, but with no luck.

DB Table:

ID INT,
SN varchar(100),
Types varchar(1000)

Sample:

ID     SN    Types
1      123   ABC,XYZ,TEST
2      234   RJK,CDF,TTT,UMB,UVX
3      345   OID,XYZ

Desired output:

ID     SN    Types
1      123   ABC    
1      123   XYZ
1      123   TEST
....

here's a cte i have to break up a delimited string

declare @table table (ID int identity(1,1), String varchar(max))
declare @delim varchar(max)

insert into @table values ('abc,def')
insert into @table values ('ghij,klmn,opqrst')

set @delim=','


;with c as
(
    select 
        ID, 
        --String,
        CHARINDEX(@delim,String,1) as Pos,
        case when CHARINDEX(@delim,String,1)>0 then SUBSTRING(String,1,CHARINDEX(@delim,String,1)-1) else String end as value,
        case when CHARINDEX(@delim,String,1)>0 then SUBSTRING(String,CHARINDEX(@delim,String,1)+1,LEN(String)-CHARINDEX(@delim,String,1)) else '' end as String
    from @table

    union all
    select
        ID,
        CHARINDEX(@delim,String,1) as Pos,
        case when CHARINDEX(@delim,String,1)>0 then SUBSTRING(String,1,CHARINDEX(@delim,String,1)-1) else String end as Value,
        case when CHARINDEX(@delim,String,1)>0 then SUBSTRING(String,CHARINDEX(@delim,String,1)+1,LEN(String)-CHARINDEX(@delim,String,1)) else '' end as String
    from c
    where LEN(String)>0
)

select ID, Value from c
declare @T table(ID int, SN varchar(100), Types varchar(1000))

insert into @T
select 1, 123, 'ABC,XYZ,TEST' union all
select 2, 234, 'RJK,CDF,TTT,UMB,UVX' union all
select 4, 234, 'XXX' union all
select 3, 345, 'OID,XYZ'

;with cte(ID, SN, Types, Rest) as
(
  select ID,
         SN,
         cast(substring(Types+',', 1, charindex(',', Types+',')-1) as varchar(100)),
         stuff(Types, 1, charindex(',', Types), '')+','
  from @T
  where len(Types) > 0
  union all
  select ID,
         SN,
         cast(substring(Rest, 1, charindex(',', Rest)-1) as varchar(100)),
         stuff(Rest, 1, charindex(',', Rest), '')
  from cte
  where len(Rest) > 0
)
select ID, SN, Types
from cte
order by ID

I use a recursive CTE to split the string. The third column Types is populated with the first word in the Types column of @T. Stuff will then remove the first word and populate the Rest column that then will contain everything but the first word. After UNION ALL is the recursive part that basically do the exact same thing but it uses the CTE as a source and it uses the rest column to pick the first word. The first word of the rest column is removed with stuff and then ..... well it is recursive so I think I will stop here with the explanation. The recursive part will end when there are no more words left where len(Rest) > 0 .

You will need to use a cursor and a while statement as far as I can tell... Some of these indexes may be off by one, but I think this should get you there...

DECLARE MY_CURSOR Cursor 
FOR
SELECT ID, SN, Types
FROM Tbl1
Open My_Cursor 
DECLARE @ID int, @SN varchar(100), @types varchar(1000)
Fetch NEXT FROM MY_Cursor INTO @ID, @SN, @types
While (@@FETCH_STATUS <> -1)
BEGIN
  DECLARE @Pos int
  WHILE @Pos < LEN(@types)
  BEGIN
    DECLARE @type varchar(25)
    DECLARE @nextpos int
    set @nextpos = CHARINDEX(@types, ',', @pos)
    SET @type = SUBSTRING(@types, @pos, @nextpos-@pos)
    INSERT INTO tbl2 (ID, SN, type) VALUES (@ID, @SN, @Type)
    SET @Pos = @nextpos+1
  END


FETCH NEXT FROMMY_CURSOR INTO @VAR1Number, @VAR2DateTime ,@VarLongText 
END
CLOSE MY_CURSOR
DEALLOCATE MY_CURSOR

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM