How to sort NULL values last using Eloquent in Laravel

匿名 (未验证) 提交于 2019-12-03 01:59:02

问题:

I've got a many to many relationship between my employees and groups table. I've created the pivot table, and all is working correctly with that. However, I've got a sortOrder column on my employees table that I use to determine the order in which they display. Employee with a value of 1 in the sortOrder column should be first, value of 2 should be second, so on. (Or backwards if sorted descending) The sortOrder column is a integer column that allows null values.

I've set up my group model to sort the employees by the sort column, but I've run into a problem. The null values always are displayed first. I've tried using ISNULL and similar SQL methods in place of the regular "asc" or "desc" used, but I only get an error.

Here's the code in my Group model:

class Group extends Eloquent {  public function employees()     {         return $this->belongsToMany("Employee")->orderBy('sortOrder', 'asc');     } } 

And here's what I use in the controller to access my model:

$board = Group::find(6)->employees; 

What's the trick in Laravel to sorting NULL values last?

回答1:

public function employees() {     return $this         ->hasMany('Employee')         ->select(['*', DB::raw('IF(`sortOrder` IS NOT NULL, `sortOrder`, 1000000) `sortOrder`')])         ->orderBy('sortOrder', 'asc'); } 

Explanation:
The IF statement solves the issue here. If NULL value is found, some big number is assigned to sortOrder instead. If found not NULL value, real value is used.



回答2:

Just add a minus sign to field and change order to DESC.

$q->orderBy(\DB::raw('-`sortOrder`'), 'desc'); 


回答3:

Laravel does not take into consideration the ISNULL method however, you can pass it in as a raw query and still make use of it as it's more efficient than if statements and the results will stay the same if you ever go beyond 1000000 employees, like so:

public function employees() {     return $this->hasMany('Employee')                 ->orderBy(DB::raw('ISNULL(sortOrder), sortOrder'), 'ASC'); } 


回答4:

Instead of relying on an arbitrary large number you can also do:

public function employees() {     return $this         ->hasMany('Employee')         ->select(['*', DB::raw('sortOrder IS NULL AS sortOrderNull')])         ->orderBy('sortOrderNull')         ->orderBy('sortOrder'); } 

It has an added benefit of being supported by SQLite.



回答5:

In Laravel 5.2 or higher just call orderByRaw. You even able to sort through aggregated value rather than a column. In the following example max_st can be null if there is no submodels.

Model::where('act', '2')     ->leftJoin('submodels', 'model.id', '=', 'submodels.model_id')     ->select('models.*', DB::raw('MAX(submodels.st) as max_st')),     ->orderByRaw('max_st DESC NULLS LAST'); 


回答6:

A workaround for PostgreSQL

For numeric types:

DB::table('t')     ->select(['id', 'val'])     ->orderBy(DB::raw("coalesce(val, 0)"), 'desc') 

For text types:

orderBy(DB::raw("coalesce(val, '')"), 'desc') 

The trick is to replace NULL values in the sorting column to zero (or empty string) so that it could be sorted as an ordinary integer (or text) value.



回答7:

->orderBy('sortOrder', 'is', 'null')->orderBy('sortOrder', 'asc') 

Seems to work.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!