Order by highest hasmany - laravel

I have two tables Parts has many Offers.
I need to get all Parts sorted by Offers highest price or quantity, where offers price > 0 and offers quantity > 0.
Price and quantity are calculated fields.
How to achieve this?
I tried
Part::
addSelect([
'quantity' => Offer::select('quantity')
->orderBy('quantity', 'desc')
->whereColumn('part_id', 'parts.id')
->limit(1)
])
->orderBy('quantity', 'desc')
->paginate(3)
But this way i cannot filter parts by quantity > 0 and price > 0
Also since quantity is calculated field when i do this
->addSelect([
'qty' => Offer::select(['quantity * 2 as qty'])
->orderBy('qty', 'asc')
->whereColumn('part_id', 'parts.id')
->limit(1)
])
I get Reference 'qty' not supported error
More explanation:
Each Part has many Offers.
Each Offer has many Shippings.
Offer`s
available_quantity = quantity - sum of shipped quantities
I need to show Parts where available_quantity > 0 and sort Parts by available_quantity

You can order it like this:
$shipping = Shipping::groupBy('offer_id')->select(DB::raw('SUM(quantity) AS sum_quantity'), 'offer_id', 'id');
Part::join('offers', 'offers.part_id', '=', 'parts.id')
->join(DB::raw("({$shipping->toSql()}) AS ship"), 'ship.offer_id', '=', 'offers.id')
->select('parts.*',DB::raw('MAX(offers.quantity - ship.sum_quantity) AS avaliable_quantity'))
->groupBy('part.id')
->orderBy('avaliable_quantity', 'desc')
->paginate(3)

Related

Eloquent - Multiple sum on the same relationship

The models I have are : Quote and Payment
A Quote hasMany Payments
A Payment belongsTo a Quote
A Payment has an 'amount' and a boolean 'is_received' fields
I'm trying to make a single query that fetches :
All the Quotes
For each Quote the sum of the received payments amounts
For each Quote the sum of all the payments amount
What I currently have is the following query... it is missing the sum of the received payments, which I have no idea how to implement (also I'm not sure this is a good approach for get the total sum anyway) :
$quotes = Quote::with([
'payments' => function ($query) {
$query->selectRaw('quote_id, SUM(payments.amount) AS payments_total')->groupBy('quote_id');
}
])
->get();
Thanks.
maybe you could use something like this:
Quote::with(['payments' => function ($query) {
$query->selectRaw(
"SUM(amount) AS payments_total," .
"SUM(IF is_received = " . true . " THEN amount ELSE 0 END) AS
received_amount");
}])->get();

Laravel return restaurants with their rate average

<?php
$query = $this->restaurant->leftJoin('reviews', 'reviews.restaurant_id', '=', 'restaurants.id');
$query = $user_id == null ? $query : $query->where("user_id", $user_id);
$query = $query->select('restaurants.*')
->selectRaw('ROUND(AVG(reviews.rating), 1) as average_rating')
->groupBy('restaurants.id')
->havingRaw('AVG(reviews.rating) >= ?', [$request->from_rating])
->havingRaw('AVG(reviews.rating) <= ?', [$request->to_rating])
->orderByDesc("average_rating")
->paginate(
$this->perPage,
['id', 'name', 'image', 'description', 'filesystem', 'created_at'],
'page',
$request->page
);
return $query;
My query looks like this. I have two tables: Restaurants and Reviews. The Reviews table stores restaurant_id. The problem occurs when we have, for example, 10 restaurants and we have 1 Review only for one of the Restaurants. After running this query, only 1 restaurant is returned, because I use havingRaw which filters Restaurants according to the average rating. So if a Restaurant doesn't have any rating, that Restaurant doesn't get returned.
How do I make that so all Restaurants still return, but their average rating becomes 0?
you can use CASE WHEN to populate mysql with more specific condition. Also you may change the datatype of 'rating' table to int(5), in this case all the empty value will be shown as 0. So that will go as you want according to your question.

Sort by condition

I'm new to laravel
I'm busy with a query to get Groups and Items ( separate models but linked )
I want to do the same as was don't for items and that is to order by $sortColumn if not null else sort by description
I'm unsure how t implement this in the given query to replace the ->orderBy('description', 'asc') with the condition.
return $this->model->with( [ 'items' => function($query){
$query->orderBy(\DB::raw("CASE WHEN ".$sortColumn." IS NOT NULL THEN ".$sortColumn."::text ELSE description END"));
}])
->where("hos_id",$hos_id)
->orderBy('description', 'asc')
->get();
I was thinking maybe
->orderBy(\DB::raw("CASE WHEN ".$sortColumn." IS NOT NULL THEN ".$sortColumn."::text ELSE description END"));
instead of
->orderBy('description', 'asc')
I guess simply
...
->orderBy(DB::raw('CASE WHEN ...'))
...

How to display most recent record added to database at the bottom in laravel?

I want display the record in descending order and by using orderBy it is working, but it is displaying in top( i need to view records like in chat most recent at bottom, but now i am getting as mail most recent top) can any one help me.
$data = DB::table("chatbox")
->where('dept_name',Session::get('dept_name'))
->orderBy('created_at', 'desc')
->get();
$data = DB::table("chatbox")
->where('dept_name',Session::get('dept_name'))
->orderBy('created_at', 'ASC')
->get();
just change desc to ASC
If you want to do it like messaging app style (last added record at the bottom), you could do this:
Make sure you know how many records you want to show at one page, for example, 10 records
Do your query as usual, to pull the last 10 records you want to show (sort by created_at, desc)
Now you should have 10 latest records on hand. In your view, you do an ascending sort on the created_at, then render them. So this will cause oldest record on top, and latest record at bottom.
Additionally:
Whenever there is a new record comes in, you can just append it into the list.
If the user need more data (pull down or something), you fetch 10 more records, and at your view, sort all records ascending, and render it again.
You can sort the collection after getting the results:
https://laravel.com/docs/5.5/collections#method-sortby
$collection = collect([
['name' => 'Desk', 'price' => 200],
['name' => 'Chair', 'price' => 100],
['name' => 'Bookcase', 'price' => 150], ]);
$sorted = $collection->sortBy('price');
$sorted->values()->all();
$data = DB::table("chatbox")
->where('dept_name',Session::get('dept_name'))
->orderBy('created_at', 'desc')
->paginate(20);
$sorted = $data->sortBy('created_at');
$sorted->values()->all();
I did not test it but you might give it a try.

Laravel Eloquent - where with and

Pic for table in blade:
and
See this pic for table in database:
In my advanced search I have 2 input box which is round 1 and round 2.
If I search for 1 in round 1 and also 1 in round 2 it should display only the data of id 1.
It's like:
$query->where(['column.round' => 1, 'column.score' => $request->score1] and ['column.round' => 2, 'column.score' => $request->score2]);
My question is how to have and operator with this to show only the data of id 1.
This is like multiple rows with the same id in 1 column.
if i get you right u only want one RAW back instead of a collection
if that is the case then:
$query->where(['round1' => 1, 'round2' => 1])->first();
Can you try this code. Refer here
$query->where(function ($roundQuery) {
$roundQuery->where('round', '=', 1)
->orWhere('round', '=', 2);
})
->where(function ($scoreQuery) use($request) {
$scoreQuery->where('score', '=', $request->score1)
->orWhere('score', '=',$request->score2);
})
->get();

Resources