Opened 7 years ago

Last modified 5 weeks ago

#13312 new New feature

Add a way to customize the order_by() of null fields

Reported by: Sergey Dobrov Owned by: nobody
Component: Database layer (models, ORM) Version: master
Severity: Normal Keywords: ordering, order_by, null
Cc: contact@…,…, markus.magnuson@…, josh.smeaton@…, github@… Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: yes
Easy pickings: no UI/UX: no


Applying order_by on null=True fields gives different results on mysql and pgsql: pgsql thinks that NULL values are bigger than any and mysql that smaller. I think that this must be unified on all engines for prevent problems with portability. pgsql has additional parameter for this:

SELECT select_list
    FROM table_expression
    ORDER BY sort_expression1 [ASC | DESC] [NULLS { FIRST | LAST }]
             [, sort_expression2 [ASC | DESC] [NULLS { FIRST | LAST }] ...]

But I don't know how it on other engines.

Change History (18)

comment:1 Changed 7 years ago by James Bennett

Needs documentation: unset
Needs tests: unset
Patch needs improvement: unset
Resolution: wontfix
Status: newclosed

I think this is one of those cases where we really just have to tell people to know the behavior of the DB they choose to use; NULL-handling in all its many forms is one of those things that's just not worth the time and complexity of abstraction.

comment:2 Changed 7 years ago by Sergey Dobrov

that's ok, but there is no way to control this behavior. i mean that i can't tell pgsql that i want nulls to be less than others in any good way. :(

comment:3 Changed 6 years ago by chexum

Keywords: null added

Just to document it, there is a very easy way to control this behavior. The most portable seems to be an additional order by for "field IS NULL". It puts NULLs last in at least sqlite3, mysql and PostgreSQL. The reverse is either "field IS NULL DESC" or "field IS NOT NULL".

It's also easy to use in a Django way:

    q = q.extra(select={'null1':'field1 is null','null2':'field2 is null'})
    q = q.extra(order_by=['null1','-field1','-null2','field2'])

Because it's so easy to do in a standard way, it might be worth at some point to add a specific queryset for it (not necessarily modifying order_by()), as extra() is not always desirable. Having a new queryset would allow backend specific optimization, like nulls last/first if supported.

comment:4 Changed 6 years ago by Benny Daon

thanks chexum

comment:5 Changed 8 months ago by Daniel Hahler

Easy pickings: unset
Severity: Normal
Type: Uncategorized
UI/UX: unset

See, which uses a specilaized QuerySet/Query.

The extra() approach is deprecated, and won't work with foreign keys / joined tables.

Last edited 8 months ago by Daniel Hahler (previous) (diff)

comment:6 Changed 8 months ago by Josh Smeaton

Resolution: wontfix
Status: closednew

Now that we have expressions, I think it's fine to reopen this ticket. We can introduce a OrderNulls.last()/.first() expression to handle this in a standard way. We could also just build it right into the OrderBy expression:


If we do build this into the existing order_by, you'll need to be careful about preserving a 'feature' that stops django from inserting duplicate ordering clauses (it builds each component then does a string compare to ensure the new clause isn't a duplicate).

This won't normalise order by nulls across backends, but it'll allow users to control null handling semantics if they have a use for it. NULL handling was originally going to be added to the OrderBy expression, but I ran out of time before that could happen.

comment:7 Changed 8 months ago by Tim Graham

Summary: order_by on null-field gives different results on different db enginesAdd a way to customize the order_by() of null fields
Triage Stage: UnreviewedAccepted
Type: UncategorizedNew feature
Version: 1.1master

comment:8 Changed 7 months ago by Ionel Cristian Mărieș

Cc: contact@… added

comment:9 Changed 6 months ago by Serhiy Zahoriya

Cc:… added

comment:10 Changed 6 months ago by Serhiy Zahoriya

AFAIU, it's possible in all main supported engines:

ORDER BY IF(ISNULL(my_field),1,0),my_field in MySQL
[NULLS { FIRST | LAST }] in both PostgreSQL and Oracle
ORDER BY col1 IS NULL in SqLite3

comment:11 Changed 4 months ago by Markus Amalthea Magnuson

Cc: markus.magnuson@… added

comment:12 Changed 4 months ago by Josh Smeaton

Cc: josh.smeaton@… added

comment:13 Changed 3 months ago by Richard Eames

Cc: github@… added

comment:14 Changed 3 months ago by Simon Charette

Has patch: set

comment:15 Changed 2 months ago by Tim Graham

Patch needs improvement: set

Comments for improvement are on the PR. Please uncheck "Patch needs improvement" after you update it an add documentation (see our PatchReviewChecklist).

comment:16 Changed 2 months ago by Simon Charette

Patch needs improvement: unset

comment:17 Changed 7 weeks ago by Tim Graham

Needs documentation: set

comment:18 Changed 5 weeks ago by Tim Graham

Needs documentation: unset
Patch needs improvement: set
Note: See TracTickets for help on using tickets.
Back to Top