1

Trying to sort descending A->Z on some podcast titles, I only want A-Z and 0-9, everything else should come last:

.order('title ASC')  

is giving me odd results at the start and end. The majority of the results in the middle are fine:

> ["\"Success Living\" - Dr. Leigh-Davis",
  "\"The Real Deal\" with Dr. Leigh-Davis",
  "#WeThePeople_Live",
  "Alley Oop podcast",
  "Always Listening: Podcast Reviews",
  ... ### everything here is fine ### ...
  "Your Mom's House",
  "Zen Dude Fitness",
  "podCast411",
  "talk2Cleo"]

(first three, last two are odd.)

1
  • Solved the last two by going lowercase: .order('lower(title) ASC') Commented Feb 10, 2016 at 21:15

2 Answers 2

2

Replace .order('title ASC') with this longer argument:

.order("
    CASE WHEN lower(title) BETWEEN 'a' AND 'zzzzz'
              OR title BETWEEN '0' AND '99999'       
         THEN lower(title)
         ELSE concat('zzzzz', lower(title))
    END")

This will sort case insensitive (lower); when values start with a digit or letter they are sorted normally, and all the other values will be sorted as if they were prefixed by 'zzzzz', forcing them to the end of the sort order.

Demo in SQL Fiddle

With Regular Expression

This solution combines the above idea with the idea of PJSCopeland (to use a regular expression). Again the strings starting with non-alphanumerical characters are sorted after those that start with alphanumerical characters:

.order("regexp_replace(lower(title), '([^[:alnum:] ])', 'zzz\1', 'gi')")

The \1 back-references the non-alphanumerical character that was matched, so all of them get prefixed with zzz.

Demo in SQL Fiddle

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

Comments

0

Disclaimer: I haven't tested this. It comes from the documentation for Postgres 9.1.

I have an inexact solution - the difference being that punctuation will simply be ignored, and your entries will end up like this:

.order("regexp_replace(title, '\W', '', 'gi')") # ASC is optional

=> ["Alley Oop podcast",
  "Always Listening: Podcast Reviews",
  "podCast411",
  "\"Success Living\" - Dr. Leigh-Davis",
  "talk2Cleo"
  "\"The Real Deal\" with Dr. Leigh-Davis",
  "Your Mom's House",
  "#WeThePeople_Live",
  "Zen Dude Fitness"]
  • regexp_replace is the Postgres equivalent of Ruby [g]sub.
  • \W means 'any non-word character' and will match anything other than A-Z, a-z, 0-9, and _.
    • If you want to ignore underscores as well, change \W to [\W_].
  • '' is what you replace the matches with: an empty string.
  • the g flag means 'all matches', and the i flag means 'case-insensitive' (dispensing with the need for lower()).

Comments

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.