I am working on a project where I need to export product sold report in Excel format. I am using Maatwebsite/Laravel-Excel
I have three Model.
product.php
class products extends Model
{
protected $table='products';
public $timestamps = false;
protected $fillable = ['image', 'asin','price','strategy_id'];
public function orderDetails()
{
return $this->hasMany(order_details::class, 'SKU', 'asin');
}
}
orders.php
class orders extends Model
{
protected $table = 'orders';
public $timestamps = false;
protected $fillable = ['id','date','quantity','totalAmount'];
public function orderDetails()
{
return $this->hasMany(order_details::class);
}
}
order_details.php
class order_details extends Model
{
protected $table = 'order_details';
protected $fillable = ['id','order_id','SKU','unitPrice','quantity','totalPrice'];
public function order()
{
return $this->belongsTo(orders::class);
}
Now I want to calculate how many time the each product sol in the last 30 days, 60 days and 90 days.
Points to note
- products.asin = order_detils.SKU
- The order_detail table does not have order date column.
- One order can have many products with quantity more than 1.
My current query is:-
$products = products::query();
// Some where clauses/filters
$products = $products->get();
foreach($products as $product)
{
// Getting the order_details which has this product
$orderIds = order_details::where('SKU','=',$product->asin)->pluck('order_id');
$product->sales30days = orders::whereIn('id', $orderIds)->whereBetween('date', [Carbon::now()->subDays(30), Carbon::now()])->sum('quantity');
$product->sales60days = orders::whereIn('id', $orderIds)->whereBetween('date', [Carbon::now()->subDays(60), Carbon::now()])->sum('quantity');
$product->sales90days = orders::whereIn('id', $orderIds)->whereBetween('date', [Carbon::now()->subDays(90), Carbon::now()])->sum('quantity');
$product->sales120days = orders::whereIn('id', $orderIds)->whereBetween('date', [Carbon::now()->subDays(120), Carbon::now()])->sum('quantity');
$product->totalSold = orders::whereIn('id', $orderIds)->sum('quantity');
}
The above query is giving me the results I need, but is taking a lot of time and is not performance friendly. I have more than 100k products.
- I there any solution to optimize this query?
- Can I add pagination like
$products->paginate(100)after this foreach loop?
date <= 120 days. You won't need all these products. You will get the "only" product's which are in the orders that aredate <= 120 days. It will be filtered version on data layer. Then you can iterate them on application layer.