如何为字符串中两个定界符之间的每个字符生成单独的行

时间:2019-02-18 20:41:55

标签: sql-server

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

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

感谢任何人都可以帮忙

3 个答案:

答案 0 :(得分:5)

这里不需要功能,当然也不需要循环。理货表将使这个工作简短。首先,您需要一个理货表。我在系统上保留一个视图。太讨厌了!!!

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

答案 1 :(得分:1)

我这样做是因为我这样做了。

select distinct *
    ,[base]+substring(splitter,number,1)
from
(
select  SomeID
    -- split your column into a base plus a splitter column
    ,[base] = left(string,charindex('[',string)-1)
    ,splitter = substring(string, charindex('[',string)+1,len(string) - charindex('[',string)-1)


from
(
-- converted your insert into a union all
SELECT 1 SomeID,  'S0000X-T859XX[DEFGH]' string
union all
SELECT 1,   'T880XX-T889XX[DS]'
union all
SELECT 2,  'V0001X-Y048XX[DS]'
union all
SELECT 2,   'Y0801X-Y0889X[AB]'
) a
) inside
cross apply (Select number from master..spt_values where number>0 and number <=len(splitter)) b -- this is similar to a tally table using an internal SQL table

答案 2 :(得分:0)

由于您没有尝试解决此问题,因此我认为您不会停留在任何特定技术上,而是在寻求高级方法。

我将通过首先创建一个表值函数来解决此问题,该函数将idstring作为参数,并通过在方括号之间循环查找字符来创建输出表,这样函数的输出看起来像这样

ID    String         Character
1     S0000X-T859XX  D
1     S0000X-T859XX  E
1     S0000X-T859XX  F
..
2     V0001XD-Y048XX D
etc...

然后,您只需编写一个查询,即可将原始表连接到IDString上不带括号的部分中的函数。