SQL函数拆分字符串和concat子字符串

时间:2020-04-05 10:44:50

标签: sql sql-server tsql

我正在尝试创建一个函数,该函数将从表中获取一列,对于单元格中的每个字符串,它将拆分成单独的单词,并连接每个单词separatley以创建不同的子字符串。我一直在研究如何使用SQL等数组来管理它,但是我没有运气

两个表是:

Account(AccountID(PK), Name, Country)
accountSubstring(subID(PK), AccountID, Substring)

理想情况下,我需要一个可以从Account的“名称”列中提取的函数。对于每一行,它将把字符串分成单独的单词,然后通过字符串separatley连接每个单词。然后,这些新创建的子字符串将作为“子字符串”输入到accountSubstring表中,并且该子字符串属于原始表中的AccountID。

例如,如果要更好地解释,如果“名称”中的名称之一是“ Stack Overflow Ireland Ltd”,则预期结果将是:

Stack
StackOverflow
StackOverflowIreland
StackOverflowIrelandLtd
Overflow
OverflowIreland
OverflowIrelandLtd
Ireland
IrelandLtd
Ltd

我需要遍历每个新创建的拆分词和concat,直到到达最后一个词。上面的每一项都将作为新行插入到accountSubstring中,但具有与来自相同原始字符串的相同AccountID。

“帐户”表有成千上万的行,将需要对所有表进行处理。这是一项匹配服务,子字符串用于比较。

希望我已经清楚要做什么,非常感谢。

2 个答案:

答案 0 :(得分:0)

这使您先前的问题适应于使用表而不是常量。这是一个示例:

with words as (
      select a.accountid, s.value as word, row_number() over (partition by a.accountid order by charindex(s.value, a.name)) as seqnum
      from account a cross apply
           string_split(a.name, ' ') s
     ),
     cte as (
      select accountid, seqnum, convert(varchar(max), word) as combined, format(seqnum, '000') as seqnums
      from words w
      union all
      select cte.accountid, w.seqnum, concat(cte.combined, ' ', w.word), concat(seqnums, ':', format(w.seqnum, '000'))
      from cte join
           words w
           on cte.accountid = w.accountid and w.seqnum = cte.seqnum + 1
     )
insert into accountSubstring (AccountId, Substring)
    select cte.accountId, cte.combined
    from cte
    order by accountid, seqnums;

db <>小提琴是here

答案 1 :(得分:0)

首先创建编号表。

SELECT TOP (4000)
    n = ISNULL(CONVERT(integer, ROW_NUMBER() OVER (ORDER BY (SELECT NULL))), 0)
INTO dbo.tblNumber1
FROM sys.columns AS c
CROSS JOIN sys.columns AS c2


CREATE UNIQUE CLUSTERED INDEX cuq
ON dbo.tblNumber1 (n)
WITH (MAXDOP = 1, SORT_IN_TEMPDB = ON);

然后创建分割字符串功能

CREATE FUNCTION [dbo].[DelimitedSplitString] (
    @pString VARCHAR(8000)
    ,@pDelimiter CHAR(1)
    )
RETURNS TABLE
    WITH SCHEMABINDING
AS
RETURN
WITH cteStart(N1) AS (
        SELECT 1

        UNION ALL

        SELECT t.number + 1
        FROM dbo.tblNumber1 t
        WHERE number < datalength(@pString)
            AND SUBSTRING(@pString, t.number, 1) = @pDelimiter
        )
    ,cteLen(N1, L1) AS (
        SELECT s.N1
            ,ISNULL(NULLIF(CHARINDEX(@pDelimiter, @pString, s.N1), 0) - s.N1, 8000)
        FROM cteStart s
        )

SELECT ItemNumber = ROW_NUMBER() OVER (
        ORDER BY l.N1
        )
    ,Item = SUBSTRING(@pString, l.N1, l.L1)
FROM cteLen l;

最终脚本,

    DECLARE  @Input table( id int identity(1,1),pString VARCHAR(2000)) 
insert into @Input values
('Stack Overflow Ireland Ltd')
,('Replace a sequential set of numbers with special character')

declare @pDelimiter CHAR(1)=' '

declare @t table (id int,itemNum int,Item varchar(50))
INSERT INTO @t
SELECT i.id
    ,ca.ItemNumber
    ,ca.Item
FROM @Input I
CROSS APPLY (
    SELECT ItemNumber
        ,Item
    FROM [dbo].[DelimitedSplitString](pString, @pDelimiter)
    ) ca;

WITH CTE
AS (
    SELECT *
    FROM @t t
        ,dbo.tblNumber1 n
    WHERE n.number <= t.itemNum
    )
SELECT id
    ,(
        SELECT '' + item
        FROM cte c1
        WHERE c.id = c1.id
            AND c.number = c1.number
            AND c1.itemNum <= c.itemNum
        FOR XML path('')
        )
FROM CTE c
ORDER BY id
    ,number
    ,itemNum