Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Laravel 基于数据库字段使用两种不同的orderBy逻辑(null/非null)_Laravel_Eloquent_Query Builder - Fatal编程技术网

Laravel 基于数据库字段使用两种不同的orderBy逻辑(null/非null)

Laravel 基于数据库字段使用两种不同的orderBy逻辑(null/非null),laravel,eloquent,query-builder,Laravel,Eloquent,Query Builder,我正在尝试根据字段是否为空来排序查询 所以,如果minute字段为null,我希望使用orderBy id;否则,我想使用两组不同的orderBy 这显示了分钟不为空的场景: public function events() { return $this->hasMany(Event::class) ->orderBy('minute', 'desc') ->orderByRaw('type = ? desc', 'period')

我正在尝试根据字段是否为空来排序查询

所以,如果minute字段为null,我希望使用orderBy id;否则,我想使用两组不同的orderBy

这显示了分钟不为空的场景:

public function events() {
   return $this->hasMany(Event::class)
        ->orderBy('minute', 'desc')
        ->orderByRaw('type = ? desc', 'period')
        ->orderByDesc('external_event_id')
}
我想要实现的是类似以下伪代码的东西:

public function events() {
   return $this->hasMany(Event::class)
        ->when('minute is NULL', function($q) {
            $q->orderByDesc('id');
        })
        ->when('minute is NOT NULL', function($q) {
            $q->orderBy('minute', 'desc')
              ->orderByRaw('type = ? desc', 'period')
              ->orderByDesc('external_event_id');
        });
}

有没有办法使用Laravel查询生成器实现这一点?

查询生成器具有whereNull和whereNotNull函数 您可以构建每个查询并将其合并,如下所示:

public function events() {
   $q1 =  $this->hasMany(Event::class)
        ->whereNull('minute')->orderByDesc('id')->get();
        
   $q2 =   $this->hasMany(Event::class)
        ->whereNotNull('minute')
         ->orderBy('minute', 'desc')
         ->orderByRaw('type = ? desc', 'period')
          ->orderByDesc('external_event_id')->get();

    //collection union
    return $q1->union($q2);
}

一个肮脏的黑客可以接近你想要的

为模型上的事件定义两种不同的关系

公共功能事件为零分钟 { 返回$this->hasManyEvent::class ->whereNull'minute' ->orderByDesc'id'; } 非空分钟的公共功能事件 { 返回$this->hasManyEvent::class ->whereNotNull'minute' ->按“分钟”、“描述”排序 ->orderByRaw'type=?desc','period' ->orderByDesc“外部事件id”; } 并在模型上定义一个方法,以在events键下合并所有事件

公共活动 { 返回static::with['eventsWithNullMinute','eventsWithNonNullMinute'] ->其中'id',$this->id ->得到 ->mapfunction$记录{ $events=collect[]; 如果$record->eventsWithNullMinute->count{ $events->push$record->eventsWithNullMinute; 取消设置$record->eventsWithNullMinute; } 如果$record->eventsWithNonNullMinute->count{ $events->push$record->eventsWithNonNullMinute; 取消设置$record->eventsWithNonNullMinute; } $record->events=$events; 返回$record; }->摘下“事件”; }
似乎不合逻辑,分钟字段是事件表的一列,对吗?不同的行/记录可能具有不同的值,或者某些行/记录也可能具有空值。对整个结果行集合进行排序。想象一下,即使可以基于列值更改排序,在一组(比如100行)中,排序也会更改多次。所以这是不符合逻辑的,如果我的答案很完美,让我知道,因为我没有tested@Donkarnash嗯,我明白你的意思,但对我来说有点不同。假设我的模型叫公共汽车。对于某些总线事件,我知道所有分钟字段都为空。对于其他人来说,分钟信息是存在的。因此,我的想法在这种情况下是有意义的,不是吗?在这种情况下,我认为下面@Abilogos的答案是最接近预期结果的答案。它基本上是将查询分为两部分:获取分钟为null的所有记录并按id对其排序,然后另一个查询获取分钟不为null的所有记录并按不同的顺序对其排序,然后合并结果。是的,@Abilogos answer是有意义的,但不幸的是unionAll打乱了排序。我也试过联合,但排序又失败了。我试过你的代码。虽然这是有道理的,但毕竟;打乱了秩序。如果我尝试单独返回$q1或$q2,它仍然可以工作。是否有其他建议取代unionAll?是的,如果在指定哪个规则比其他规则集更优先时有两个不同的规则,那么您正确的排序毫无意义。例如,第一个集合具有更高的优先级。我建议首先->获取第一个集合,然后->获取另一个集合,然后联合集合,然后返回它们,但在查询级别执行此操作比在集合级别执行两个单独的DB事务和排序更理想。使用get两次也会破坏关系:/Check这个方法:谢谢,再使用一次也行,但确实很肮脏。我会仔细考虑一下,然后再重新考虑。