36

我的员工和组表之间存在多对多关系。我已经创建了数据透视表,并且一切正常。但是,我的员工表上有一个 sortOrder 列,用于确定它们的显示顺序。sortOrder 列中值为 1 的员工应该排在第一位,值为 2 的员工应该排在第二位,以此类推。(如果按降序排序,则向后) sortOrder 列是允许空值的整数列。

我已经设置了我的组模型以按排序列对员工进行排序,但是我遇到了一个问题。始终首先显示空值。我尝试使用 ISNULL 和类似的 SQL 方法代替使用的常规“asc”或“desc”,但我只得到一个错误。

这是我的 Group 模型中的代码:

class Group extends Eloquent {

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

这是我在控制器中用来访问我的模型的内容:

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

Laravel 最后对 NULL 值进行排序的技巧是什么?

4

9 回答 9

71

Laravel 没有考虑该ISNULL方法,但是,您可以将其作为原始查询传递并仍然使用它,因为它比IF语句更有效,并且如果您超过 1000000 名员工,结果将保持不变(接受的答案),像这样:

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

更新: 您还可以使用orderByRaw()方法:

public function employees()
{
    return $this->hasMany('Employee')
                ->orderByRaw('ISNULL(sortOrder), sortOrder ASC');
}
于 2015-04-19T15:57:29.557 回答
32

只需在字段中添加一个减号并将顺序更改为 DESC。

$q->orderBy(\DB::raw('-`sortOrder`'), 'desc');
于 2015-07-29T21:49:21.377 回答
10

在 Laravel 5.2 或更高版本中,只需调用orderByRaw. 您甚至可以通过聚合值而不是列进行排序。在以下示例max_st中可以是null如果没有子模型。

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');
于 2016-09-20T08:41:13.287 回答
6
public function employees()
{
    return $this
        ->hasMany('Employee')
        ->select(['*', DB::raw('IF(`sortOrder` IS NOT NULL, `sortOrder`, 1000000) `sortOrder`')])
        ->orderBy('sortOrder', 'asc');
}

说明:
IF 语句解决了这里的问题。如果找到 NULL 值,则将一些大数字分配给 sortOrder。如果发现不是 NULL 值,则使用实际值。

于 2013-07-14T22:08:38.727 回答
5

您还可以执行以下操作,而不是依赖于任意大数:

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

SQLite 支持它还有一个额外的好处。

于 2014-02-13T08:09:41.940 回答
5

我最近使用 Laravel 5.6 遇到了这个问题,其中 junkystu 的答案对我来说是完美的。但是我们的测试框架使用 sqlite,所以测试不断返回 500 错误。

这就是我们想出的,它应该与 DB 驱动程序稍微无关。

上升

$query->orderBy(DB::raw('column_to_sort IS NULL, column_to_sort'), 'asc');

降序

$query->orderBy(DB::raw('column_to_sort IS NOT NULL, column_to_sort'), 'desc');
于 2018-08-08T13:14:26.373 回答
0

PostgreSQL 的解决方法

对于数字类型:

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

对于文本类型:

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

诀窍是将NULL排序列中的值替换为零(或空字符串),以便可以将其排序为普通整数(或文本)值。

于 2016-03-18T11:21:59.047 回答
0

您可以更优雅地执行以下操作以获得更好的结果

  1. 这将按最新到最旧和 null 到最后。

     ->orderByRaw("CASE WHEN column_to_order IS NULL THEN 0 ELSE 1 END DESC")
     ->orderBy('column_to_order', 'DESC')
    
    
  2. 这将首先排列空记录,然后从最旧到最新排列。

   ->orderByRaw("CASE WHEN column_to_order IS NULL THEN 0 ELSE 1 END ASC")
   ->orderBy('column_to_order', 'ASC')
于 2022-02-07T12:45:40.363 回答
-1
->orderBy('sortOrder', 'is', 'null')->orderBy('sortOrder', 'asc')

似乎工作。

于 2015-04-18T19:03:53.473 回答