【问题标题】:How to sort NULL values last using Eloquent in Laravel如何在 Laravel 中使用 Eloquent 对 NULL 值进行最后排序
【发布时间】:2013-07-12 17:12:55
【问题描述】:

我的员工和组表之间存在多对多关系。我已经创建了数据透视表,并且一切正常。但是,我的员工表上有一个 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 值的技巧是什么?

【问题讨论】:

    标签: php many-to-many laravel eloquent


    【解决方案1】:

    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');
    }
    

    【讨论】:

    • 这也是适用于非数值(如日期)的有效解决方案。
    • 恕我直言,这是最简单的解决方案。
    • 我试过但得到 mysql 错误。但是通过在顺序的两边添加`来修复'ISNULL(`sortOrder`), `sortOrder` ASC'
    【解决方案2】:

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

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

    【讨论】:

    • 对于 laravel 5.1:$q->orderBy(\DB::raw('-sortOrder'), 'desc');
    • 对于 Laravel 5.4:$q->orderByRaw("-start_date",'DESC')
    • 对于 Laravel 5.6:$query->orderByRaw('-start_date DESC')(注意单个字符串而不是第二个参数)。
    • 之前的评论有误,应该是$query->orderByRaw('-`start_date` DESC')
    【解决方案3】:

    在 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');
    

    【讨论】:

      【解决方案4】:
      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 值,则使用实际值。

      【讨论】:

      • 谢谢!这完美!我不知道在 Eloquent 中可以使用 Fluent 链方法。
      • 你能告诉我选择中括号的重要性吗?我对他们有一个奇怪的问题。我有两台开发计算机,其中一台没有括号问题,另一台抛出 FatalErrorException。我把它们拿出来了,现在两台电脑都可以用了,我的查询结果好像没变。
      • 传递给select() 方法的括号只不过是数组的新语法。您会遇到问题,因为此功能是 PHP 5.4 附带的新功能。您的一台计算机运行 5.4,另一台不运行。见php.net/manual/en/language.types.array.phpphp.net/manual/en/migration54.new-features.php
      • 这看起来是个坏习惯。
      【解决方案5】:

      您还可以这样做:

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

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

      【讨论】:

        【解决方案6】:

        我最近使用 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');
        

        【讨论】:

          【解决方案7】:

          PostgreSQL 的解决方法

          对于数字类型:

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

          对于文本类型:

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

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

          【讨论】:

            【解决方案8】:
            ->orderBy('sortOrder', 'is', 'null')->orderBy('sortOrder', 'asc')
            

            似乎有效。

            【讨论】:

            • 实际上,这会创建一个包含 order by sortOrder DESC, sortOrder ASC 的查询,该查询不会最后添加 NULL 值。
            • @junkystu:你是如何验证的?我还没有设法让 SQL 日志记录工作。我正在使用 Eloquent 5.0 顺便说一句。
            • 使用debug bar,它非常好,甚至可以让您查看通过 ajax 运行的查询以及其他有用的东西
            猜你喜欢
            • 2017-04-30
            • 1970-01-01
            • 2020-05-23
            • 1970-01-01
            • 2016-08-04
            • 2015-03-27
            • 2018-02-10
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多