来自 SQL 的 Laravel Eloquent ORM 聚合函数

Posted

技术标签:

【中文标题】来自 SQL 的 Laravel Eloquent ORM 聚合函数【英文标题】:Laravel Eloquent ORM aggregate functions from SQL 【发布时间】:2014-06-07 07:18:35 【问题描述】:

我正在为一个项目使用 Laravel 4。

我有两张表,“拍卖”和“出价”,我想获取所有出价最低的拍卖。 (我想得到所有的“投标”模型)

我可以在 SQlite 中为每个拍卖编写查询,例如:

select *,min(bids.amount) from auctions,bids where auctions.id = bids.auction_id and auctions.id = 2 ; 

我已经设置了关系拍卖 hasMany('Bids') 和 bids belongsTo('Auction') 以便我可以调用

$auctions = Auction::with('bids')->get();

使用嵌套的 Bids 模型获得所有拍卖,以便我可以调用

$auctions->bids

在我看来访问出价。

由于我不想获取 100 个出价并计算视图中的最低价,将最低出价逻辑移入模型的最佳方法是什么?

更新

两种解决方案都有效,实际上最有效的方法是将其放入模型中

public function getLowestBidAttribute() 
        return $this->bids()->orderBy('amount','asc')->first();

由于保持应用程序的其余部分更干净,我可以定义其他方法来获取具有不同逻辑的出价。

【问题讨论】:

【参考方案1】:

您可以为此使用访问器:

// Auction model
public function getLowestBidAttribute()

  return $this->bids() 
    ->remember(1) // cache the query for a minute
    ->orderBy('amount', 'asc')->first();

// you can also check isset() lowestBid on $this->attributes, but this is a bit cleaner
// and most of the time caching query for a minute will be enough to avoid multiple queries

然后你可以很容易地访问它:

$auction->lowestBid; // Bid model you need

编辑:上面的代码对于单次拍卖来说是可以的,但是当你获取拍卖集合时,它会导致 n+1 问题,我建议在代码中处理它,但这不是问题:

// Auction model
public function bids()

  return $this->hasMany('Bid')->orderBy('amount','asc');

然后在集合上使用 first() 方法:

// $auctions = Auction::with('bids')->get();
foreach($auctions as $auction)

  $auction->bids->first(); // Bid model with lowest amount value

【讨论】:

【参考方案2】:

您可以像这样遍历拍卖并获取每个拍卖的最低出价:

foreach($auctions AS $auction) 
     echo $auction->bids->min('bid');

在拍卖模型上,结合 deczo 的答案和您要求的更好:

function getMinBidAttribute() 
   return $this->bids()->min('bid');

那么你可以这样称呼它:

foreach($auctions AS $auction) 
   echo $auction->minBid;

【讨论】:

$auction->bids->min 不会返回模型 obj,而是所有投标集合中的最低值,第二个代码也是如此,因为它将从 db 中获取最小值。跨度> 我以为他想要最低的出价,再加上所有的出价。 ->minBid 会给他最低的出价,->bids() 会给他出价集合。 bids() 返回查询生成器,因此 bids()->min(...) 运行聚合 SQL 查询( SELECT MIN() ...),同时检查集合:bids- >分钟(...)

以上是关于来自 SQL 的 Laravel Eloquent ORM 聚合函数的主要内容,如果未能解决你的问题,请参考以下文章

从 SQL 到 Laravel 8 Eloquent

Laravel 将 SQL 转换为 Eloquent:按 sum() 排序

多个 Laravel Eloquent 关系未显示来自所有关系的数据

Laravel 5 Eloquent:如何获取正在执行的原始 sql? (带有绑定数据)

用于原始 SQL 查询的等效 Laravel Eloquent

在 Laravel 5 Eloquent 中获取原始 SQL 查询的结果