I've basically copied this from this answer: https://stackoverflow.com/a/16667778/9101689
It uses patindex to identify the position of the numeric values and substrings out the actual value. We take that substring and the use the LEFT function to trim everything out to the right and cast that value as an int to order.
declare @d table (drug_id nvarchar(max))
insert into @d values ('A-1'),('A-10A'),('A-11'),('A-2'),('A-20A'),('A-21'),('A-22'),('A-3'),('A-30'),('A-31')
SELECT *
FROM (
SELECT ORD_subsrt = SUBSTRING(drug_id, ORD_pos, LEN(drug_id)), *
FROM (
SELECT ORD_pos = PATINDEX('%[0-9]%', drug_id), *
FROM @d
) d
) t
Order by cast(LEFT(ORD_subsrt, PATINDEX('%[^0-9]%', ORD_subsrt + 't') - 1) as int)
The value t is added so the patindex '%[^0-9]%' will return a non zero value in the case there is no non numeric suffix on drug_id field.
Or less readable:
SELECT *
From @d
Order by cast(LEFT(SUBSTRING(drug_id, PATINDEX('%[0-9]%', drug_id), LEN(drug_id)), PATINDEX('%[^0-9]%', SUBSTRING(drug_id, PATINDEX('%[0-9]%', drug_id), LEN(drug_id)) + 't') - 1) as int)
This won't work properly if you have a value like "A2-10A" though (or anything with more than one numeric value).