2

Let say I have a table with one column, i.e.:

5 absolute
5.0
5.1
last
50
5 elite
edge

I need to order this to (using postgresql methods):

5 absolute
5 elite
5.0
5.1
50
edge
last

But if I use classic "ORDER BY column ASC" I get:

50
5.0
5.1
5 absolute
5 elite
edge
last

There are a lot of tools like substring or using, but I can't understand how they works.

What I need to do?

0

2 Answers 2

1

Don't know, may be something like this:

with cte as (
   select col1, regexp_split_to_array(col1, ' ') as d
   from Table1

)
select col1
from cte
order by
    d[1] ~ '^([0-9]+[.]?[0-9]*|[.][0-9]+)$' desc,
    case
        when d[1] ~ '^([0-9]+[.]?[0-9]*|[.][0-9]+)$' then
            d[1]::numeric
    end,
    d[2]

sql fiddle demo

this one splits string by spaces to array, convert first entry to numeric and sorts results by this number and remaining string

Sign up to request clarification or add additional context in comments.

1 Comment

It seems to be correct, but I forgot about all string can be with just [a-z] values. So I have invalid input syntax for type numeric:. Please see updated question
0

This should do it:

order by regexp_replace(the_column, '[^0-9\.]', '', 'g')::numeric DESC

It removes all character that are non-numeric (leaves only digits and the .) from the value and then converts it into a number. That number is then used to sort descending

The only thing is that 5.0 will be sorted after 5.1 with the above.

If you need to take values into account which don't have any digits, something like this:

order by 
      case 
         when regexp_replace(the_column, '[^0-9\.]', '', 'g') <> 
            then regexp_replace(the_column, '[^0-9\.]', '', 'g')::numeric
      end DESC NULLS LAST, 
      the_column DESC -- to sort the "NULL" values alphabetically

If you don't want to repeat the regex expression you could do something like this:

with clean_data as (
   select the_column, 
          regexp_replace(the_column, '[^0-9\.]', '', 'g') as clean_column, 
          ....
   from ...
)
select *
from clean_data
order by case 
           when clean_column <> '' then clean_column::numeric 
         end desc nulls last, 
         the_column desc;

5 Comments

It seems to be correct, but I forgot about all string can be with just [a-z] values. So I have invalid input syntax for type numeric:. Please see updated question
Thanks, it works, but I think that's very difficult for just postgres
@asiniy: you can always write a function that implements the above logic and then use that function in your query (which would reduce your query to select * from some_table order by get_sort_value(the_column)
Hm. I want to use this in Rails. How I can do this in ActiveRecord?
@asiniy: I have no idea. I don't use Rails and I avoid ORMs like the plague precisely for those problems. But using a function should be much easier than using a complicated expression.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.