SQL Функция для разделения строк и конкатов подстрок - PullRequest
0 голосов
/ 05 апреля 2020

Я пытаюсь создать функцию, которая будет принимать столбец из таблицы, для каждой строки в ячейке она будет разбиваться на отдельные слова и объединять каждое слово отдельно, создавая разные подстроки. Я искал, как управлять им с помощью SQL, как массивы и т. Д., Но мне не повезло

Две таблицы:

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

В идеале мне нужна функция, которая будет принимать в столбце «Имя» из учетной записи. Для каждой строки она разделяет строки на отдельные слова, а затем объединяет каждое слово через разделительную строку. Эти вновь созданные подстроки затем будут введены в таблицу accountSubstring как «Подстрока» вместе с AccountID, которому принадлежит подстрока из исходной таблицы.

Чтобы объяснить это лучше, например, если одно из имен в ' Имя было «Stack Overflow Ireland Ltd», ожидаемый результат будет:

Stack
StackOverflow
StackOverflowIreland
StackOverflowIrelandLtd
Overflow
OverflowIreland
OverflowIrelandLtd
Ireland
IrelandLtd
Ltd

Мне нужно будет l oop через каждое вновь созданное разделенное слово и выполнить конкат, пока оно не достигнет последнего слова. Каждый из вышеперечисленных будет вставлен в accountSubstring в виде новой строки, но с тем же AccountID, что и из той же исходной строки.

Таблица Account имеет тысячи строк, и это нужно будет сделать для всех. Это сервис сопоставления, и для сравнения используются подстроки.

Надеюсь, это ясно из того, что я пытаюсь сделать, Большое спасибо заранее.

Ответы [ 2 ]

0 голосов
/ 06 апреля 2020

Сначала создайте таблицу чисел.

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);

Затем создайте функцию Split String

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
0 голосов
/ 05 апреля 2020

Это адаптирует ваш предыдущий вопрос для использования таблиц вместо констант. Вот пример:

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;

Скрипт дБ <> здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...