Ниже запрос выполняет следующее: он использует функцию patindex
для извлечения индекса в строке шаблона:
во-первых, он извлекает начало числа, ища цифру.
Во-вторых, извлекается конец числа в поисках цифры, за которой следует не цифра.
Сделав это, мы имеем все дляизвлечь число из строки и отсортировать его после преобразования (приведения) в целое число.
Попробуйте этот запрос:
declare @tbl table (col1 varchar(50));
insert into @tbl values
('Btc0504'),
('Btc0007_Shd_7'),
('Btc0007_Shd_6'),
('MR_Tst_Btc0565'),
('Btc0004_Shd_4'),
('Btc_Btc0605');
select col1 from (
select col1,
PATINDEX('%[0-9]%', col1) [startIndex],
case PATINDEX('%[0-9][^0-9]%', col1) when 0 then LEN(col1) else PATINDEX('%[0-9][^0-9]%', col1) end [endIndex]
from @tbl
) [a]
order by CAST(SUBSTRING(col1, startIndex, endIndex - startIndex + 1) as int)
Я нашел другое решение, которое очень компактнои более общий:
;with cte as (
select 1 [n], col1, STUFF(col1, PATINDEX('%[^0-9]%', col1), 1, '.') refined_col1 from @tbl
union all
select n+1, col1, STUFF(refined_col1, PATINDEX('%[^0-9.]%', refined_col1), 1, '.') from cte
where n < 100 -- <--this number must be greater than the greatest amount of non-digits in a col1, this way, you are sure that you'll remove all unnecesary characters
)
select col1, refined_col1 from cte
where PATINDEX('%[^0-9.]%', refined_col1) = 0
order by CAST(replace(refined_col1, '.', '') as int)
option (maxrecursion 0)