using sum with relation Laravel Eloquent ORM - sql

i have Model Material which has
protected $with = ['costPrices'];
public function costPrices(){
return $this->hasMany(CostPrice::class);
}
the table of cost_prices has multiple quantity
//create_cost_prices_table
Schema::create('cost_prices', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('material_id');
$table->unsignedBigInteger('supplier_id');
$table->integer('quantity');
$table->timestamps();
});
i want to get (insufficient materials ) in another way select all materials form materials table where sum of all quantities of cost_prices table < 3 and get me the resulted materials not the count

You have 2 options:
You could fix your option with whereHas() by adding select and groupBy:
$materials = Material
::whereHas('costPrices', function($q) {
$q
->select('meterial_id')
->groupBy('material_id')
->havingRaw('SUM(quantity) > 4');
})
->get();
Or use subquery:
For laravel 6.x:
$materials = Material
::addSelect([
'cost_prices_sum' => CostPrice::selectRaw('sum(quantity)')->whereColumn('material_id', 'material.id')
])
->having('cost_prices_sum', '>', 4)
->get();
For laravel 5.x:
$materials = Material
::selectRaw('carts.*, (select sum(quantity) from cost_prices where cost_prices.matrerial_id = meterials.id) as cost_prices_sum')
->having('cost_prices_sum', '>', 4)
->get();
UPDATE: option with whereHas() is faster on a large number of rows.

Related

Covert SQL to Laravel Query Builder

I'm a beginner regarding Laravel Query Builder, can you guys help me convert this SQL to Query Builder
public function check_available_room(Request $request, $checkin_date)
{
$available_rooms = DB::SELECT("SELECT * FROM rooms WHERE id NOT IN (SELECT room_id FROM bookings WHERE '$checkin_date' BETWEEN checkin_date AND checkout_date)");
}
Book model
function rooms() {
return $this->belongsTo(Room::class, 'room_id');
}
Room model
public function bookings() {
return $this->hasMany(Booking::class);
}
Thank you so much
Here is a solution if you have your models and relations in place
$availableRooms = Room::whereDoesntHave('bookings', function($bookingQuery) use ($checkin_date) {
$bookingQuery->where('checkin_date', '<', $checkin_date)
->where('checkout_date', '>=', $checkin_date);
})->get();
$unavailable_room_ids = Booking::where('checkin_date', '<', $checkin_date)
->where('checkout_date', '>=', $checkin_date)
->pluck('room_id')->get();
$available_rooms = Room::whereNotIn('id', $unavailable_room_ids)->get();

Laravel sum nested relationship column

I tried sum nested related column but get empty result.
Code:
$data = CropType::with(['categories' => function($cq) {
return $cq->with(['varieties' => function($vq) {
return $vq->with(['products' => function($pq) {
return $pq->sum('total');
}]);
}]);
}])->get();
As you can see, I have 4 tables that are interconnected with foreign keys
Table: crop_types
id
title
Table: categories
id
title
crop_type_id
Table: varieties
id
title
category_id
Table: products
id
title
total
variety_id
But when I run my query it's run as like this instead summing total products:
"select * from crop_types"
How I can correctly sum total products in each crop type?
Try this query to get total products in each crop type:
SQL
SELECT crop_types.id,
crop_types.title AS title,
sum(products.total) AS total
FROM `products`
INNER JOIN `varieties`
ON `varieties`.`id` = `products`.`variety_id`
INNER JOIN `categories`
ON `categories`.`id` = `varieties`.`category_id`
INNER JOIN `crop_types`
ON `crop_types`.`id` = `categories`.`crop_type_id`
GROUP BY `crop_types`.`id`
Laravel Eloquent
$result = Product::query()
->selectRaw('crop_types.id, crop_types.title as title, sum(products.total) as total')
->join(
'varieties',
'varieties.id',
'=',
'products.variety_id'
)
->join(
'categories',
'categories.id',
'=',
'varieties.category_id'
)
->join(
'crop_types',
'crop_types.id',
'=',
'categories.crop_type_id'
)
->groupBy('crop_types.id')
->get();

multiple joins with the same table in eloquent

Is there some elegant way to write the following query in eloquent? I would like to avoid using the raw query:
results(id, data)
result_filters (id, result_id, filter_id, value)
SELECT * FROM results, result_filters as age, result_filters as followers
WHERE age.result_id = results.id
AND followers.result_id = results.id
AND age.filter_id = 2
AND age.value > 90
AND followers.filter_id = 6
AND followers.value < 10000
If you are using the laravel eloquent
your model relation could be like
model Result:
public function resultFilters()
{
return $this->hasMany('App\ResultFilter');
}
model ResultFilter:
public function result()
{
return $this->belongsTo('App\Result','result_id');
}
try the below code:
$result = Result::find(1);
$data = $result->resultFilter()
->whereIn('filter_id',[2,6])
->whereBetween('value',[90,10000])
->get();
What do you think? It's uses DB::raw but it works
$data = DB::table(DB::raw("results, result_filters as age, result_filters as followers "))
->select(DB::raw("* "))
->where('age.result_id', 'results.id')
->where('followers.result_id', 'results.id')
->where('age.filter_id', 2)
->where('age.value', '<', 90)
->where('followers.filter_id',6)
->where('followers.value','<',10000)
->get();

Doctrine QueryBuilder multiple distinct

I would like to restrict results with DISTINCT on two columns using doctrine ORM
My function is like this :
public function findFdvLinkedToPdv($pointVenteCodes){
$queryBuilder =
$this->createQueryBuilder('r')
->leftJoin('r.forceVente', 'forceVente')
->leftJoin('r.pointVente', 'pointVente')
->leftJoin('r.signature', 'signature')
->leftJoin('signature.affaire', 'affaire')
->andWhere('pointVente.code IN (:pointvente_codes)')
->orderBy('forceVente.matricule', 'ASC')
->addOrderBy('pointVente.code', 'ASC')
->addOrderBy('affaire.code', 'ASC')
->addOrderBy('r.type', 'ASC')
->setParameters(array('pointvente_codes' => $pointVenteCodes,))
->select(array(
'forceVente.matricule AS forcevente_matricule',
'pointVente.code AS pointvente_code',
'affaire.code AS affaire_code',
'r.id AS id',
'r.profil AS profil',
'r.type AS type',
'forceVente.nom AS nom',
'forceVente.prenom AS prenom',
'forceVente.email AS email',
'r.deletedAt AS deletedAt'));
return $queryBuilder->getQuery()->getArrayResult();
}
For each forcevente.matricule and each pointVente.code , I have from 2 to 6 rows. I would like to get one row for each couple forcevente.matricule/pointVente.code I have to do a distinct on both columns, but when I try :
->select(array(
'DISTINCT forceVente.matricule AS forcevente_matricule',
'DISTINCT pointVente.code AS pointvente_code',
'affaire.code AS affaire_code', etc ...
I have a doctrine error ...
[EDIT]
I do this in PHP after executing the request to filter the results...
//BEGIN PATCH
$i=0;
$linkedForceVentes2 = array();
foreach ($linkedForceVentes as $item) {
if (!isset($linkedForceVentes2[$item['pointvente_code']][$item['forcevente_matricule']])){
$linkedForceVentes2[$item['pointvente_code']][$item['forcevente_matricule']] = $item;
}else{
unset($linkedForceVentes[$i]);
}
$i++;
}
//END PATCH
I finaly resolved it with a groupBy :
->groupBy('forcevente_matricule', 'pointvente_code', 'type' , 'affaire_code');
Just after the select statement.

How to select items by providing where clause in pivot

This is my code looks like right now :
$result = Category::with(array(
"getProducts",
"getProducts.getBrand",
"getProducts.getImages",
"getProducts.getDetail",
"getProducts.getTax",
"getProducts.getDiscount",
"getProducts.getAttributes" => function($query) use($_temp){
if($_temp != null){
$query->where_in('attributes.id',$_temp);
}
},
"getSlideshow",
"getSlideshow.getItems",
"getAttributeListing",
"getAttributeListing.getAttributes",
"getAttributeListing.getAttributes.productSpecific"
))
->where('id','=', $category_id)
->first();
Yet, It only filters the getProducts.getAttributes items not the 'getProducts' itself. Is there a way that I can get the Products by attributes?
Note: I am using Laravel 3