SQL Server, T-SQL, есть ли более быстрый способ подстановки следующей строки в моем вопросе? - PullRequest
0 голосов
/ 15 января 2010

У меня есть строки вроде

ОТКРЫТЫЕ СИСТЕМЫ SUB GR (GM / BTIB (1111) / BTITDBL (2222) / BTVY (4444) / ACSVTYSAG)

в моей базе данных под моей колонкой ГРУПП.

Что я хочу сделать, это извлечь 2222 из этой строки. Код, который я использую, выглядит следующим образом.

    SELECT 
        SUBSTRING(GROUPS, CHARINDEX('(',GROUPS, CHARINDEX('(',GROUPS, CHARINDEX('(',GROUPS,0)+1)+1)+1, 4 ) AS GroupNo

    FROM MY_TABLE

    WHERE

    ISNUMERIC(SUBSTRING(GROUPS, CHARINDEX('(',GROUPS, CHARINDEX('(',GROUPS, CHARINDEX('(',GROUPS,0)+1)+1)+1, 4 )) = 1

Мне нужно закрепить приведенный выше код, либо изменив способ подстроки, который я использую, либо изменив некоторую логику. Можете ли вы сказать мне, что можно улучшить в моем коде?

Ответы [ 3 ]

1 голос
/ 15 января 2010

Вы можете реализовать UDF CLR, который реализует regex .

1 голос
/ 15 января 2010

Реализация на основе множеств.

Это менее производительно, чем ваш код для отдельных строк, но лучше масштабируется для больших наборов результатов, особенно если вы заменяете CTE, генерирующую таблицу динамических чисел, на таблицу статических чисел.

DECLARE @t TABLE
(groups VARCHAR(250))

INSERT @t
VALUES ('OPEN SYSTEMS SUB GR (GM/BTIB(1111)/BTITDBL(2222)/BTVY(4444)/ACSVTYSAG)')

INSERT @t
VALUES ('OPEN SYSTEMS SUB GR (GM/BTIB(1111)/BTITDBL(3333)/BTVY(4444)/ACSVTYSAG)')

DECLARE @chr_delim CHAR(1)
SET @chr_delim = '('

-- nums_cte generates a dynamic numbers table
-- replace this with your own numbers table if you have one
;WITH nums_cte 
AS 
( 
        SELECT 1 AS n 
        UNION ALL 
        SELECT n+1 FROM nums_cte 
        WHERE n < 250
) 
,splitCTE    
AS
(
        SELECT  SUBSTRING(s,n,CHARINDEX(@chr_delim, s + @chr_delim,n) -n) AS ELEMENT
                ,s
                ,ROW_NUMBER() OVER (PARTITION BY s
                                    ORDER BY n
                                   ) AS rn
        FROM (SELECT groups AS s FROM @t) AS D
        JOIN nums_cte
        ON n <= LEN(s)
        AND SUBSTRING(@chr_delim + s,n,1) = @chr_delim 
)
SELECT LEFT(ELEMENT,4) AS GroupNo
       ,s AS originalString
FROM splitCTE
WHERE rn = 4
AND   ISNUMERIC(LEFT(ELEMENT,4)) = 1
OPTION (MAXRECURSION 0)
1 голос
/ 15 января 2010

Если вы делаете это часто, я бы рассмотрел анализ данных о вставке / обновлении / удалении с помощью триггера в отдельную таблицу (скажем, MY_TABLE_ELEMENTS), а затем SELECT из MY_TABLE, соединенного с MY_TABLE_ELEMENTS.

Вы можете, например, использовать функцию split (разделение на "(", если я правильно понимаю ваш код), сохранение либо каждого целого элемента split в MY_TABLE_ELEMENTS, либо разбор только числовой части.

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