首页 > 解决方案 > 如何为字符串中两个分隔符之间的每个字符生成单独的行

问题描述

我有一个带方括号的数据集。

CREATE TABLE Testdata
(
    SomeID INT,
    String VARCHAR(MAX)
)

INSERT Testdata SELECT 1,  'S0000X-T859XX[DEFGH]'
INSERT Testdata SELECT 1,   'T880XX-T889XX[DS]'
INSERT Testdata SELECT 2,  'V0001X-Y048XX[DS]'
INSERT Testdata SELECT 2,   'Y0801X-Y0889X[AB]'

我需要得到如下输出,

SomeId  String 
1       S0000XD-T859XXD
1       S0000XE-T859XXE
1       S0000XF-T859XXF
1       S0000XG-T859XXG
1       S0000XH-T859XXH
1       T880XXD-T889XXD
1       T880XXS-T889XXS
2       V0001XD-Y048XXD
2       V0001XS-Y048XXS
2       Y0801XA-Y0889XA
2       Y0801XB-Y0889XB

感谢是否有人可以提供帮助

标签: sql-server

解决方案


这里不需要函数,当然也不需要循环。一个计数表可以解决这个问题。首先,您需要一个计数表。我保留一个作为我系统的视图。速度太快了!!!

create View [dbo].[cteTally] as

WITH
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)),
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max
    cteTally(N) AS 
    (
        SELECT  ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4
    )
select N from cteTally
GO

您没有使用这样的视图,您可以直接在代码中使用 CTE。

这是一些相当丑陋的字符串操作,但由于您的数据没有正确规范化,您有点卡在那里。请尝试此查询。它产生你所说的你期望的输出。

select *
    , NewOutput = left(td.String, charindex('-', td.String) - 1) + SUBSTRING(td.String, CHARINDEX('[', td.String) + t.N, 1) + 
        left(substring(td.String, charindex('-', td.String), len(td.String)), charindex('[', substring(td.String, charindex('-', td.String), len(td.String))) - 1) + SUBSTRING(td.String, CHARINDEX('[', td.String) + t.N, 1)
from TestData td
join cteTally t on t.N <= CHARINDEX(']', td.String) - CHARINDEX('[', td.String) - 1
order by td.String
    , t.N

推荐阅读