Laravel Query with Sum of value from child table if value column in parent table greater than sum of value in child - laravel

I am trying to query for rows from transaction table where the amount is less than sum of allocations against that transaction row in allocations table. This works halfway. It is giving me all transaction queries with an additional field of "allocated_amount".
$all_transactions = Transaction::
withCount([
'allocations AS amount_allocated' => function ($query) {
$query->select(
DB::raw("CAST(SUM(amount) AS INTEGER)"
));
}
])
->where('contact_type','supplier')
->where('contact_id',$ehead->supplier_id)
->get()->toArray();
Result
0 => array:12 [▼
"id" => 4
"amount" => 10000
"created_by" => 1
"amount_allocated" => 7500
]
1 => array:12 [▼
"id" => 5
"amount" => 10000
"created_by" => 1
"amount_allocated" => 10000
]
But I don't want the second result to come up because amount = amount allocated. How to fix this query?
Tried using:
->where('amount','>','allocated_amount')
but maybe because it is additionally added filed, throws an error saying allocated field does not exist. I need it within the query, not as a separate addition.

Well, in this case you can simply use map()
$all_transactions = collect($all_transactions)->map(function ($row) {
if ($row['amount'] > $row['amount_allocated']) {
return $row;
}
})->filter()->toArray(); // filter() to remove null values

Related

Need to Get data of ID ( received in Array ) from database

Good Morning. I am trying to get the data for each BuffaloID which i get in array. From that ID i am trying to get milk record for each buffaloID. But 2nd query give the data for first id only. How can i get the data for each id.
Query
$buffalidforavgmilk = Buffalomilkrecord::groupBy('buffaloID')->get('buffaloID')
->pluck('buffaloID')->toArray();
array:4 [▼
0 => "Buffalo-01"
1 => "Buffalo-02"
2 => "Buffalo-03"
3 => "Buffalo-04"
]
When i try below query i received data only for first id
$avgbuffalomilk = Buffalomilkrecord::where('buffaloID',$buffalidforavgmilk)->
pluck('totalmilk')->toArray();
array:5 [▼
0 => "9.00"
1 => "13.00"
2 => "12.00"
3 => "13.00"
4 => "12.00"
]
I hope i describe my problem and where did i make mistake to get data for all ID
Thanks in Advance
use whereIn
$buffalidforavgmilk = ['1','2','3'];
$avgbuffalomilk = Buffalomilkrecord::whereIn('buffaloID',$buffalidforavgmilk)->pluck('totalmilk')->toArray();

Laravel whereHas not filtering as expected

The 2 models involved are JobRequest and StationJob. Really their relationship is oneToMany. I have a relationship set up for this $jobRequest->stationJobs().
Further to this I need a hasOne relationship latestStation, based on the same model. I need this relationship to filter my collection of JobRequests based on whether the JobRequest has a latestStation equal to a specified station.
I am expecting to get an empty list of JobRequests because I know the latestStation is equal to id 3 and I am filtering for id 2. Instead I get the jobRequest, with latestStation id 3 even though I am filtering for 2.
Relationship
public function latestStationTest()
{
return $this->hasOne(StationJob::class)->whereNotNull('finished')->latest();
}
Controller
$stationId = $request->station_id;
$jobRequests = JobRequest::with(['latestStationTest'])->whereHas('latestStationTest', function($query) use ($stationId) {
$query->where('station_id', $stationId);
})->get();
Query Result
[2020-10-17 07:39:07] local.INFO: array (
0 =>
array (
'query' => 'select * from `job_requests` where exists (select * from `station_jobs` where `job_requests`.`id` = `station_jobs`.`job_request_id` and `station_id` = ? and `finished` is not null)',
'bindings' =>
array (
0 => 2,
),
'time' => 1.0,
),
1 =>
array (
'query' => 'select * from `station_jobs` where `finished` is not null and `station_jobs`.`job_request_id` in (1) order by `created_at` desc',
'bindings' =>
array (
),
'time' => 0.5,
),
)
I've tried...
Switching with() before or after whereHas makes no difference.
adding ->where() to with() selects the StationJob with the specified id, instead of checking if the latestStation id is equal to the specified id.

How to get last 7 days records with 0 counts

I have an eloquent query that gets the total count records (created_at) of the last 7 days. But the problem is if one of these days have 0 records, this doesn't appear in the final data.
My query:
$data = Data::whereBetween('created_at', [Carbon::now()->subDays(6)->format('Y-m-d')." 00:00:00", Carbon::now()->format('Y-m-d')." 23:59:59"])
->groupBy('date')
->orderBy('date')
->get([
DB::raw('DATE(created_at) as date'),
DB::raw('count(*) as total')
])
->pluck('total', 'date')->toArray();
What I get:
[
"2020-04-14" => 1
"2020-04-16" => 1
"2020-04-18" => 1
"2020-04-19" => 1
]
What I expected:
[
"2020-04-14" => 1
"2020-04-15" => 0
"2020-04-16" => 1
"2020-04-17" => 0
"2020-04-18" => 1
"2020-04-19" => 1
"2020-04-20" => 0
]
Any suggestions?
SOLUTION:
-Based on Gary Houbre's proposal:
$results = Data::whereBetween('created_at', [Carbon::now()->subDays(6)->format('Y-m-d')." 00:00:00", Carbon::now()->format('Y-m-d')." 23:59:59"])
->groupBy('date')
->orderBy('date')
->get([
DB::raw('DATE_FORMAT(created_at, "%Y-%m-%d") as date'),
DB::raw('count(*) as total')
])
->keyBy('date')
->map(function ($item) {
$item->date = Carbon::parse($item->date);
return $item;
});
$period = new DatePeriod(Carbon::now()->subDays(6), CarbonInterval::day(), Carbon::now()->addDay());
$graph = array_map(function ($datePeriod) use ($results) {
$date = $datePeriod->format('Y-m-d');
return $results->has($date) ? $results->get($date)->total : 0;
}, iterator_to_array($period));
Looking directly Sql : How to include "zero" / "0" results in COUNT aggregate?
Into a same table : How to get the record if Count is zero in Laravel
You need to add an outer join into your request with Eloquent.
My idea is to create a for loop to check the days.
If there is no record on a date then print 0
Loop Iteration:
Catch the first Day (Suppose 14)
Catch the last Day
Then check in every iteration it is greater than one or many
Thus, I hope you will get normally.
We had a similar problem while trying to put back-end data into the chart. Since some of the days were missing it didn't look well. Our solution was;
Create a function like this;
public function generateDates(Date $startDate, Date $endDate, $format = 'Y/m/d'): Collection
{
$dates = collect();
$startDate = $startDate->copy();
for ($date = $startDate; $date->lte($endDate); $date->addDay()) {
$dates->put($date->format($format), 0);
}
return $dates;
}
In your case it's going to be (today and today - six days) and you will union returning collection with your query collection. What it does is; it create a date range from the keys and fill them with zero. When your query collection has some value other than zero - it is going to overwrite it.

How to filter using eloquent using distinct?

Would like for some help. Currently I have a table with multiple records.
Columns have is : id, identifier, price
I would like to write a query which I'm able to get the unique identifier with the highest price only.
I would like the collection to be
[
[
'id' => 5,
'identifier' => 1001
'price' => 50
],
[
'id' => 7
'identifier' => 1002,
'price' => 35
]
]
the first array id is 5 because from the identifier 1001 the highest price is 50 and the id is 5 and second array id is 7 because identifier 1002 highest price is 35
$maxPrices = Model::select(DB::raw('max(price)'))
->groupBy('identifier')->get();
query result: [50, 35]
Model::select()->whereIn('price',$maxPrices)->orderBy('price', 'desc')->get()
query result
[
[
'id' => 5,
'identifier' => 1001
'price' => 50
],
[
'id' => 7
'identifier' => 1002,
'price' => 35
]
]
Use this to get all distinct identifiers with max price (edit table):
$products = DB::table('tbl_products')->groupBy('identifier')->get(['identifier', DB::raw('MAX(price) as price')]);
Hi guys found a better solution. Read on DB view table. This function will create a virtual table with the value wanted and in laravel you can create a model to reference that virtual table and do eloquent query on it.

Group the result of an already grouped query sql/laravel

Hello everyone this is my first post and after giving this a lot of work my head just doesn't want to cooperate anymore, I've searched online for answers but can't find related cases, I am working in laravel 5.2 with a query, said query is to get the progress on items and count the items that share the same progress to display in a pie chart.
Relations are as follows:
I have 3 tables:
Items
Steps to complete (each one has a percentage).
Progress of each item per step (Completed true or false)
Right now I have this code
table('items as i')
->join('items_sectors as is', 'i.sector_id', '=', 'is.id')
->join('sectors_steps_progress as stp', 'i.id', '=', 'stp.item_id')
->join('sectors_steps as cs', 'stp.step_id', '=', 'cs.id')
->where('stp.completed', true)
->selectRaw('count(distinct i.id) as count, CONCAT(sum(cs.percentage), "%") as percentage')
->groupBy('stp.completed', 'i.id');
And this with some testing data outputs
array:3 [▼
0 => {#2042 ▼
+"count": 1
+"percentage": "50%"
}
1 => {#2043 ▼
+"count": 1
+"percentage": "100%"
}
2 => {#2044 ▼
+"count": 1
+"percentage": "100%"
}
]
What I want is to now join all the matchings "percentage" and count them so it would end up like:
array:3 [▼
0 => {#2042 ▼
+"count": 1
+"label": "50%"
}
1 => {#2043 ▼
+"count": 2
+"label": "100%"
}
]
Thanks a lot if anyone can help me with this, I'm still trying to figure it out :(
if result is not a collection convert it to a collection and apply the code below
$result = $array->groupBy("percentage")
->map(function($q){
$newArray['count'] = count($q);
$newArray['percentage'] = $q[0]['percentage'];
return $newArray;
})->values();
return $result;
Hope it helps.

Resources