Below is the result that you are after, but I doubt that this is proof of a fool. I think you are going to fight for a solution that is infallible and still works well.
The first part is to get the first number (where this happens after the space, so Campsite no.41 handled differently with Campsite no. 40 ), I put this in APPLY to make it easy to reuse the result.
The next step is to search for the first non-numeric character after the first number, that is, where the number ends, so that we can extract the full number using a substring, and then finally use TRY_CONVERT(INT to get this fragment in the sortable type.
SELECT s.Section, TextPart = SUBSTRING(s.Section, 1, ISNULL(fn.FirstNumber, LEN(s.Section))), Number = CASE WHEN FirstNumber IS NULL THEN NULL ELSE TRY_CONVERT(INT, SUBSTRING(s.section, fn.FirstNumber + 1, ISNULL(ln.LastNumber, LEN(s.Section)))) END FROM dbo.Section AS s
nb You will need to move the expressions in select in order and not in the alias of the column, but I left it in this format to make it more clear what is happening
I tried to comment on the solution, but there is an honest cue ball, so a full explanation of each bit will be quite complicated. Sorry if something is unclear
EDIT
Sorry, I missed the update, where you switched from desire (test1, test11, test2) to (test1, test2, test11). It just changes your logic to look for the first letter, but now it's the one where the previous character is not complete ( PATINDEX('%[^.][0-9]%', s.section) ), not where the previous character was still space (this ensures that Campsite no.20 sorted after Campsite no. 40 )
SELECT s.Section, TextPart = SUBSTRING(s.Section, 1, ISNULL(fn.FirstNumber, LEN(s.Section))), Number = CASE WHEN FirstNumber IS NULL THEN NULL ELSE TRY_CONVERT(INT, SUBSTRING(s.section, fn.FirstNumber + 1, ISNULL(ln.LastNumber, LEN(s.Section)))) END FROM