簡體   English   中英

獲取由Laravel Eloquent中父模型中的字段篩選的相關列的SUM

[英]Get SUM of a related column filtered by a field in the parent model in Laravel Eloquent

我有以下表格:

訂單

  • ID
  • 狀態

line_items

  • ID
  • purchase_order_id
  • PRODUCT_ID
  • 數量

制品

  • ID
  • 產品名稱

采購訂單包含多個訂單項 ,每個訂單項都有一個產品和一個數量字段(' qty ')。

請參閱ERD模型

以下是我定義Laravel模型的方法:

產品型號:

class Product extends Model
{
    public function lineitems()
    {
        return $this->hasMany('App\LineItem');
    }
}

LineItem模型:

class LineItem extends Model
{
    public function purchase_order()
    {
        return $this->belongsTo('App\PurchaseOrder', 'purchase_order_id');
    }

    public function product()
    {
        return $this->hasOne('App\Product', 'product_id');
    }
}

PurchaseOrder型號:

class PurchaseOrder extends Model
{
    public function lineitems()
    {
        return $this->hasMany('App\LineItem');
    }

}

我希望得到所有'line_items.qty'的SUM,其中'product.id''purchase_order.status'過濾。

如何在Model函數中編寫查詢,以便我可以使用它通過Blade @foreach遍歷所有產品?

先感謝您!

如果您希望獲得更高的速度並一次性獲取所有內容,那么您可以嘗試以下查詢:

$products = Product::selectRaw('products.*, sum(line_items.qty) as qty_sum')
            ->join('line_items', 'line_items.product_id', '=', 'products.id')
            ->join('purchase_orders', 'purchase_orders.id', '=', 'line_items.purchase_order_id')
            ->where('purchase_orders.status', 'sold')
            ->groupBy('products.id')
            ->get();

但是你的數據庫,如果MySql必須接受整個分組,其中一列總是與其他列匹配。

但是,如果您只想堅持Laravel關系,請執行以下步驟。

1-當你的表名是復數時,PK是id ,而FK是表名單數,帶有_id ex(table products(id),table line_items(product_id)),不需要在Relations中指定外鍵。

2-由於它是多對多的情況,您不一定要為中間表line_items定義模型,您可以將它用於特殊和快速查詢,但您可以通過Laravel Pivot系統處理它上面的CRUD。 您可以了解有關Pivot的更多信息https://laravel.com/docs/5.7/eloquent-relationships#many-to-many

檢索中間表列

正如您已經了解的那樣,處理多對多關系需要存在中間表。 Eloquent提供了一些與此表交互的非常有用的方法。 例如,假設我們的User對象有許多與之相關的Role對象。 訪問此關系后,我們可以使用模型上的pivot屬性訪問中間表:

所以你的模型看起來像這樣:

產品型號:

class Product extends Model
{
    public function purchaseOrders()
    {
        return $this->belongsToMany('App\PurchaseOrder', 'line_items')->withPivot('qty')->withTimestamps();
    }

    public function soldPurchaseOrders()
    {
        return $this->belongsToMany('App\PurchaseOrder', 'line_items')
                    ->where('status', 'sold')
                    ->withPivot('qty')->withTimestamps();
    }
}

PurchaseOrder型號:

class PurchaseOrder extends Model
{
    public function products()
    {
        return $this->belongsToMany('App\Product', 'line_items')->withPivot('qty')->withTimestamps();
    }

}

如果您的數據透視表有created_atupdated_at列,請使用->withPivot('field1', 'field2', 'etc')->withTimestamps() 並在查詢構建器中使用前綴pivot_ +屬性訪問數據透視值,並在結果對象方法中使用pivot-> +屬性,例如: $products->first()->pivot->qty

如果您仍想使用LineItem模型, belongsTo Product relation更改為belongsTo

LineItem模型:

class LineItem extends Model
{
    public function purchaseOrder()
    {
        return $this->belongsTo('App\PurchaseOrder');
    }

    public function product()
    {
        return $this->belongsTo('App\Product');
    }
}

3-最后用qty的SUM檢索產品使用以下代碼:

在1個請求中使用預先加載來自動加載所有產品的采購訂單,以避免N-Products + 1個數據庫請求。 https://laravel.com/docs/5.7/eloquent-relationships#eager-loading

$products = Product::with('soldPurchaseOrders')->get();

foreach($products as $product) {
    $qtySum = $product->soldPurchaseOrders->sum('pivot.qty');
    echo '<br/> Product '.$product->id.' - '.$product->name.' - '.$qtySum;
}

所以最后,Laravel將使用INNER JOIN查詢轉換它,如上面的第一個例子,但只有花哨的設計和數據透視表。

編輯 - - -

OP指定訂單狀態為sold ,我已更新要使用已銷售的代碼。

編輯2 -----

$qtySum替換$product->pivot->qty $qtySum $product->pivot->qty 在調用soldPurchaseOrders關系之后,將提供樞軸數量,例如:

foreach($product->soldPurchaseOrders as $order) {
    echo '<br/>Order .'$order->id.' - '.$order->pivot->qty;
} 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM