1

I stored string variables in a database, either 'Abstain', 'Block', 'No', or 'Yes'. Currently I am grabbing these using an ORDER BY position however, instead of alphabetic order, I would like to order them like: 'Block', 'No', 'Abstain', 'Yes'. Is there an easy way to do this in Rails?

My exact code for this is:

def self.unique_votes(motion)
  Vote.find_by_sql("SELECT * FROM votes a WHERE created_at = (SELECT MAX(created_at) as created_at FROM votes b WHERE a.user_id = b.user_id AND motion_id = #{motion.id}) ORDER BY a.position")
end

NB: I am using Postgres SQL and am looking for a solution that i can use in the select statement Thanks!

Jesse Whitham
  • 824
  • 9
  • 32

4 Answers4

7

This is one of the ways to do that. By the way, the best way to do such a thing is to have another table named "Position" that identifies every value by a number and a foreign key in the "votes" table to reference the primary key of "Position" table. Also you can have another column named "Order" in the "Position" table to store those numbers and sort with. You should do these things in the insert time, not on every select.

Cheers

SELECT  *
,   Case    a.position
        When    'Block'     Then    0
        When    'No'        Then    1
        When    'Abstain'   Then    2
        When    'Yes'       Then    3
        Else    -1
    End                     As  Position_Value
    FROM    votes   a
    WHERE   created_at =    (
        SELECT  MAX(created_at) as  created_at
            FROM    votes   b
            WHERE   a.user_id   =   b.user_id
            AND motion_id   =   #{motion.id}
    )
    ORDER   BY  Position_Value

Any way if it does not work as it should! you can try this one:

Select  *
    From    (
        SELECT  *
    ,   Case    a.position
            When    'Block'     Then    0
            When    'No'        Then    1
            When    'Abstain'   Then    2
            When    'Yes'       Then    3
            Else    -1
        End                     As  Position_Value
        FROM    votes   a
        WHERE   created_at =    (
            SELECT  MAX(created_at) as  created_at
                FROM    votes   b
                WHERE   a.user_id   =   b.user_id
                AND motion_id   =   #{motion.id}
        )
    )   As  Result
    ORDER   BY  Position_Value
Rikki
  • 3,338
  • 1
  • 22
  • 34
4

Whenever I have a series I need to sort into an unnatural order, I add an additional integer field, and put values into it that will force the string values into whatever order I want them.

Instead of having only:

'Abstain'
'Block'
'No'
'Yes'

I'd have a second field:

'Abstain' 3
'Block'   1
'No'      2
'Yes'     4

Sorting on the second column allows me to retrieve the values in my desired order:

'Block'   1
'No'      2
'Abstain' 3
'Yes'     4
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
2

If this is a permanent requirement, you can store them in a different table with another column 'ordering' that carries the number to print them in desired order, join your results with this table and ORDER BY the ordering column.

If this is a temporary, you can join your results with UNION of bunch of SQL statements that select the value and the ordering and then order by the ordering column.

Vikdor
  • 23,934
  • 10
  • 61
  • 84
  • So the suggestion is that I should create a temporary ordering table? This is not a permanent requirement and should only apply to the one part of a much bigger application, I have seen some stuff about an "ORDER BY" statement that can sort the strings out is this a possibility? – Jesse Whitham Sep 11 '12 at 04:57
0

You could define something like MySQL's FIELD function, ie an index lookup into an array, then use that for your ORDER BY. It's a bit more concise than an array.

See: https://stackoverflow.com/a/12366184/398670

Community
  • 1
  • 1
Craig Ringer
  • 307,061
  • 76
  • 688
  • 778