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();
我有两个 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();