Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specify the sort-order for an Enum field type

I have a model that uses the Enum field type:

from sqlalchemy import Column, Enum, Integer, String

class Task(Base):
    __tablename__ = 'tasks'

    id = Column(Integer, primary_key=True)
    summary = Column(String)
    priority = Column(Enum('low', 'medium', 'high'))

If I sort the records by priority (the Enum), it's sorts alphabetically:

high
low
medium

How can I specify the sort-order for this field?

like image 508
Jon Avatar asked May 12 '14 17:05

Jon


People also ask

How do you sort an enum?

We can use the natural sort order or sort by their properties. Any Enum type we create implements the Comparable interface. Below is an excerpt from the Java documentation. Enum<E> implements Comparable<E> via the natural order of the enum (the order in which the values are declared).

Does enum order matter?

The order in which the enumeration values are given matters.

What is enum data type in SQL?

An ENUM is a string object with a value chosen from a list of permitted values that are enumerated explicitly in the column specification at table creation time.

What is enum data type syntax?

Enumeration or Enum in C is a special kind of data type defined by the user. It consists of constant integrals or integers that are given names by a user. The use of enum in C to name the integer values makes the entire program easy to learn, understand, and maintain by the same or even different programmer.


1 Answers

Another way may exist, but the simplest (and most database-agnostic) solution I know of would be to use a case statement in the order by clause.

First, set up your whens dict for your case statement by getting the tuple you used to create the column's Enum:

enums = Task.priority.type.enums  # finds the Enum tuple (with the same order you originally gave it)
whens = {priority: index for index, priority in enumerate(enums)}  # dynamically creates whens dict based on the order of the Enum tuple

Or, if you must, hard code your whens dict (definitely less than ideal, since you now have to change code in two places):

whens = {'low': 0, 'medium': 1, 'high': 2}

Second, set up your sort logic in a case statement:

sort_logic = case(value=Task.priority, whens=whens).label("priority")

Third, run your query and order by your case statement:

q = session.query(Task).order_by(sort_logic)  # see the sql at the end of this answer

You now have a query sorted by your original Enum tuple:

>>> for item in q:
        print item.id, item.priority
#  now in the order you were looking for
4 low
7 low
3 medium
8 medium
2 high
6 high

Just for reference, the above query produces the following SQL:

SELECT        tasks.id AS tasks_id,
              tasks.summary AS tasks_summary,
              tasks.priority AS tasks_priority 
FROM          tasks
ORDER BY CASE tasks.priority
             WHEN :param_1 THEN :param_2
             WHEN :param_3 THEN :param_4
             WHEN :param_5 THEN :param_6
         END
like image 98
Justin O Barber Avatar answered Oct 14 '22 18:10

Justin O Barber