SQL Server 2005:如何拆分具有未知拆分次数的堆叠列

发布于 2024-11-16 14:42:55 字数 407 浏览 0 评论 0原文

我在拆分堆叠列时遇到更多问题,并且希望获得一些帮助来完成最后一部分。我试图应用我拥有的另一个解决方案,但没有运气。

DB 表:

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

示例:

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

所需输出:

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

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
....

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

软甜啾 2024-11-23 14:42:55

这是一个 cte 我必须分解一个分隔字符串

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

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
已下线请稍等 2024-11-23 14:42:55
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

我使用递归 CTE 来分割字符串。第三列 Types 使用 @T 的 Types 列中的第一个单词填充。然后,Stuff 将删除第一个单词并填充 Rest 列,该列随后将包含除第一个单词之外的所有内容。 UNION ALL 之后是递归部分,基本上执行完全相同的操作,但它使用 CTE 作为源,并使用 rest 列来选择第一个单词。 rest 列的第一个单词被 stuff 删除,然后......它是递归的,所以我想我会在这里停止解释。当没有剩余单词时,递归部分将结束
其中 len(Rest) > 0 。

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.

牛↙奶布丁 2024-11-23 14:42:55

据我所知,您将需要使用游标和 while 语句...其中一些索引可能会偏离一个,但我认为这应该可以帮助您实现...

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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文