Since I think it only looks for the next item in the string (i.e. 1, 2, 21, 3), but is there a way to treat it as an integer or make it look at the full number?
You’ll probably need to take the integer suffix of ?ID bindings to a separate variable (using xsd:integer for casting), then order by that one. Strings are sorted lexicographically.
Not directly, but one can have a user-defined function which maps values of custom datatypes to integers… That’d be another way to solve the topic starter’s problem but perhaps an overkill here.