Laravel 同一列上的多个 orderBy

Laravel multiple orderBy on same column

首先,我将包括一些我尝试过的事情,因为我认为这对我正在尝试做的事情来说是不言自明的。

$event->load(['dates' => function($q) {

 $q->where( DB::raw('DATE(start_time)'), '>=', Carbon::now()->format('Y-m-d'))
   ->orderBy('start_time', 'asc')

   ->where( DB::raw('DATE(start_time)'), '<', Carbon::now()->format('Y-m-d'))
   ->orderBy('start_time', 'desc');

}]);

$event->load(['dates' => function($q) {

 $q->where( DB::raw('DATE(start_time)'), '>=', Carbon::now()->format('Y-m-d'))
   ->orderBy('start_time', 'asc')

   ->orWhere(function($query) {

     $query->where( DB::raw('DATE(start_time)'), '<', Carbon::now()->format('Y-m-d'))
           ->orderBy('start_time', 'desc');
     });

}]);

我想做什么

我有一个 EVENTS table 与 DATES 有 hasMany 关系。我正在尝试加载相关日期 firstascending 顺序为即将到来的日期然后在 descending 为已经过去的日期排序。

无论我尝试什么,orderBy 总是排序 所有 结果而不是 where 查询。如何解决这个问题?


非常感谢 - 正确答案当然会被投票选为答案。

同一查询不能有两个不同的订单。但是,您可以拥有两个子查询,每个子查询都有自己的顺序,union按照您希望的方式组合在一起。

好的,实际上找到了两个适合我问题的解决方案。感谢 @Bernie 给了我一个正确方向的推动 - 我不能在同一个查询中有两个不同的订单并寻找类似 union / merge 的东西.


有多个查询

第一行是 Eager Loading 即将到来的日期 $event

第二,你得到 过去的日期,第三,你将它们合并在一起。

唯一的坏处 - 您必须执行多个(两个)查询,这不是最佳选择。

    $event->load(['dates' => function($q) {
        $q->where( DB::raw('DATE(start_time)'), '>=', Carbon::now()->format('Y-m-d') )
          ->orderBy('start_time');
    }]);

    $past = $event->dates()
                  ->where( DB::raw('DATE(start_time)'), '<', Carbon::now()->format('Y-m-d') )
                  ->orderBy('start_time', 'desc')                 
                  ->get();

    $event->dates = $event->dates->merge($past);

收集方法

首先,您 Eager Load 属于该事件的所有日期。

filter 所有 过去的日期 reverse 他们 - 所有这些都是通过使用 收集方法 .

然后你 count 过去的日期,splice 它们来自原始 Collection 并合并新的反向 Collection 返回。

    $event->load(['dates' => function($q) {
        $q->orderBy('start_time');
    }]);

    $filtered = $event->dates->filter(function ($item) {
        return $item->raw_date < Carbon::now()->format('Y-m-d');
    })->reverse();

    $event->dates->splice(0, $filtered->count());
    $event->dates = $event->dates->merge($filtered);

结论

第一种方法使用两个 查询,这不是最优的 - 第二种方法使用相当多的 收集方法

如果有人能指出哪一个更有效率,那将非常有帮助!