I have a table column numbers
containing strings like:
1, 2, 2A, 14, 14A, 20
Listed in the desired ascending sort order.
How can I formulate an ORDER BY
clause to achieve this order?
Per default, postgres has to resort to alphabetical order which would be:
1, 2, 14, 20, 2A, 14A
Can this be done using only the string-manipulation features that come with Postgres? (replace()
, regex_replace()
etc?)
My first idea was:
- cut the letter, if present
- number * 100
- add ascii of letter, if present
This would yield the desired result as the mapped values would be:
100, 200, 265, 1400, 1465, 2000
I could also index this manipulated value to speed up sorting.
Additional restrictions:
I cannot use casts to hex numbers, because eg.: 14Z
is valid too.
Ideally, the result is a single expression. I'd need to use this transformation for filtering and sorting like:
SELECT * FROM table WHERE transform(numbers) < 15 ORDER BY transform(numbers)
RESULT:
1, 2, 2A, 14, 14A
I tried to implement my idea, using what I learned from @klin's answer:
Cut the letter and multiply number by 100:
substring('12A' from '(\d+).*')::int*100
Cut the numbers and get ASCII of letter:
ascii(substring('12A' from '\d+([A-Z])'))
Add the two.
This works fine with 12A
, but does not work with 12
, as the second expression returns NULL
and not 0
(numeric zero). Any ideas?