Laravel leftJoin 仅加入 right table 的最后一条记录并按其排序

Laravel leftJoin only last record of right table and order by it

我有两个 table。 1) 产品 2) 价格

-------------------------
-       products        -
-------------------------
- id         | int      -
- name       | varchar  -
- created_at | datetime -
- updated_at | datetime -
-------------------------

----------------------------
-          prices          -
----------------------------
- id            | int      -
- product_id    | int      -
- sale_price    | int      -
- regular_price | int      -
- created_at    | datetime -
- updated_at    | datetime -
-----------------------------

我想搜索产品并从价格 table 中获取每个产品的最后价格。我用这个:

class Product extends Model
{
   public function lastPrice()
    {
        return $this->hasOne(Price::class)->orderBy('id', 'DESC');
    }

}

然后我使用以下方式获取包含最新价格的产品列表:

$products=Product::with('lastPrice')->paginate(9);

我的问题是:我想按 highest/lower 价格订购结果。我将如何做到这一点?

我相信使用 laravel 6 或更高版本你可以在 addSelect() 子句中使用相关的子查询作为

Product::addSelect(['latest_price' =>
                        Price::select('price')
                            ->whereColumn('product_id', 'products.id')
                            ->orderBy('id', 'desc')
                            ->limit(1)
])->orderBy('latest_price','desc')
  ->paginate(9);
  

因此,从上面我们将从数据库中获取产品数据以及最新价格列,因此您可以对 latest_price

应用排序

编辑 如果您的列数限制为 select,例如 sale_price,您可以添加另一个子查询,但如果您想从价格 table select 整行,请查看使用 join/exists

的另一种方法
Product::addSelect(['sale_price' =>
                        Price::select('sale_price')
                            ->whereColumn('product_id', 'products.id')
                            ->orderBy('id', 'desc')
                            ->limit(1),
                    'regular_price' =>
                        Price::select('regular_price')
                            ->whereColumn('product_id', 'products.id')
                            ->orderBy('id', 'desc')
                            ->limit(1),

])->orderBy('sale_price','desc')
  ->orderBy('regular_price','desc')
  ->get();

您可以 select 价格 table 的最新行以及产品数据,我现在可以想到两种方式

 // Approach 1
 Product::join('prices as a', 'products.id', '=', 'a.product_id')
        ->leftJoin('prices as a1', function ($join) {
            $join->on('a.product_id', '=', 'a1.product_id')
                 ->whereRaw(DB::raw('a.id < a1.id'));
           })
        ->whereNull('a1.product_id')
        ->select('products.*', 'a.*')
        ->orderBy('sale_price','desc')
        ->orderBy('regular_price','desc')
        ->get();

// Approach 2 with whereExists
 Product::join('prices as a', 'products.id', '=', 'a.product_id')
        ->whereExists(function ($query) {
           $query->select(DB::raw(1))
                 ->from('prices as b')
                 ->whereRaw(DB::raw('a.product_id = b.product_id'))
                 ->havingRaw('max(b.id) = a.id');
        })
        ->select('products.*', 'a.*')
        ->orderBy('sale_price','desc')
        ->orderBy('regular_price','desc')
        ->get();