SQL извлечь самый правый номер в строке и приращения - PullRequest
1 голос
/ 07 октября 2019

У меня есть коды транзакций, такие как

 "A0004", "1B2005","20CCCCCCC21"

Мне нужно извлечь самый правый номер и увеличить код транзакции на один

"AA0004"----->"AA0005"
"1B2005"------->"1B2006"
"20CCCCCCCC21"------>"20CCCCCCCC22"

в SQL Server 2012.

  • неизвестная длина строки
  • правильно (n?) Всегда число

, имеющее дело с незначительным числом строки и длиной числа, вне моей лиги. какая-то логика всегда отсутствует.

LEFT(@a,2)+RIGHT('000'+CONVERT(NVARCHAR,CONVERT(INT,SUBSTRING( SUBSTRING(@a,2,4),2,3))+1)),3

Ответы [ 3 ]

2 голосов
/ 07 октября 2019

Во-первых, я хочу прояснить это: я полностью согласен с комментариями к вопросу от a_horse_with_no_name и Jeroen Mostert.
Вы должны хранить одну точку данных на столбец, точка.

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

Сначала создайте и заполните образец таблицы ( Пожалуйста, сохраните этот шаг в ваших будущих вопросах):

DECLARE @T AS TABLE 
(
    col varchar(100)
);

INSERT INTO @T (col) VALUES
('A0004'),
('1B2005'),
('1B2000'),
('1B00'),
('20CCCCCCC21');

(я добавил пару строк в качестве крайних случаев, которые вы не упомянули в вопросе)

Тогдаиспользуя пару cross apply для минимизации повторения кода, я придумал, что:

SELECT  col,
        LEFT(col, LEN(col) - LastCharIndex + 1) + 
        REPLICATE('0', LEN(NumberString) - LEN(CAST(NumberString as int))) + 
        CAST((CAST(NumberString as int) + 1) as varchar(100)) As Result
FROM @T
CROSS APPLY
(
    SELECT PATINDEX('%[^0-9]%', Reverse(col)) As LastCharIndex
) As Idx
CROSS APPLY 
(
    SELECT RIGHT(col, LastCharIndex - 1) As NumberString
) As NS

Результаты:

col         Result
A0004       A0005
1B2005      1B2006
1B2000      1B2001
1B00        1B01
20CCCCCCC21 20CCCCCCC22

LastCharIndex представляет индекс последнего не-значный символ в строке. NumberString представляет число для приращения в виде строки (чтобы сохранить начальные нули, если они существуют).

Оттуда просто берется левая часть строки (то есть до числа) и объединить его с новой вычисляемой числовой строкой, используя Replicate для дополнения результата сложения точным числом начальных нулей, которое имела исходная числовая строка.

0 голосов
/ 08 октября 2019

STUFF (@X, LEN (@X) -CASE PATINDEX ('% [AZ]%', REVERSE (@X)), КОГДА 0 ТОЛЬКО LEN (@X) Иначе PATINDEX ('% [AZ]%',ОБРАТНЫЙ (@X)) - 1 КОНЕЦ + 1, ЛЕН (((ВПРАВО (@ X, CASE PATINDEX ('% [AZ]%', ОБРАТНЫЙ (@X)), КОГДА 0 ПОСЛЕ ЛЕН (@X), В противном случае PATINDEX ('% [AZ]% ', REVERSE (@X)) - 1 КОНЕЦ) / @ N) +1) @ N), ((ВПРАВО (@ X, CASE PATINDEX ('% [AZ]% ', REVERSE)(@X)) КОГДА 0 ПОСЛЕ ЛЕН (@X) Иначе PATINDEX ('% [AZ]%', ОБРАТНЫЙ (@X)) - 1 КОНЕЦ) / @ N) +1) @ N)

  • работает только со строками с номерами
  • 99 становится 100
  • с шагом mod (@N)
0 голосов
/ 07 октября 2019

Попробуйте

DECLARE @test nvarchar(1000) ='"A0004", "1B2005","20CCCCCCC21"'
DECLARE @Temp AS TABLE (ID INT IDENTITY,Data nvarchar(1000))
INSERT INTO @Temp 
SELECT @test

;WITH CTE
AS
(
SELECT Id,LTRIM(RTRIM((REPLACE(Split.a.value('.' ,' nvarchar(max)'),'"',''))))  AS Data
,RIGHT(LTRIM(RTRIM((REPLACE(Split.a.value('.' ,' nvarchar(max)'),'"','')))),1)+1 AS ReqData
FROM
(
SELECT ID,
CAST ('<S>'+REPLACE(Data,',','</S><S>')+'</S>' AS XML) AS Data
FROM @Temp
) AS A
CROSS APPLY Data.nodes ('S') AS Split(a)
)
SELECT CONCAT('"'+Data+'"','-------->','"'+CONCAT(LEFT(Data,LEN(Data)-1),CAST(ReqData AS VARCHAR))+'"') AS ExpectedResult
FROM CTE

Результат

ExpectedResult
-----------------
"A0004"-------->"A0005"
"1B2005"-------->"1B2006"
"20CCCCCCC21"-------->"20CCCCCCC22"
...