SilverStripe - sum() a limited list of dataobject variables - php

In SilverStripe I want to calculate the sum of only the first three DataObjects, to get a sub amount.
I tried the following but the function always returns the sum of all DataObjects and not only the first three.
public function getSubSum() {
$service = ServiceProvided::get()->filter(array(
'InvoiceObjectID' => $this->ID
));
$sum = $service->limit(3, 0)->sum('Sum');
return $sum;
}
How do I calculate the sum of only the first three DataObjects?

The SUM is calculated first, and and then the limit is applied after the aggregate sum function has already been calculated. In effect you're asking it to calculate the sum first, which returns a single row, and then limit that result to three rows.
To do this you will probably need to use a subquery like:
SELECT SUM("Sum") FROM (SELECT "Sum" FROM "ServiceProvided" WHERE ... LIMIT 3)
To execute custom SQL in SilverStripe you can use DB::query(). However, you need to be careful when doing this to avoid SQL injection. A simpler approach would just be to calculate the sum in PHP.

To calculate the sum in PHP use a for loop to go through each database row returned, and add the value to a variable.
public function getSubSum() {
$services = ServiceProvided::get()
->filter('InvoiceObjectID', $this->ID)
->limit(3, 0);
$sum = 0;
foreach($services as $service) {
$sum += $service->Sum;
};
return $sum;
}

Related

Get() method to pull data and then foreach

I intend to pull all the rows that have same order ID from an orderDetail table using the get() method and loop through to add all the values of the tax column to a $total_ variable. Then I planned to add the $total_ to the seller balance.
I want to get the sum of the tax values in column that get pulled out with the same order_id. I have tried to use the sum() but there seem to still be error. The only thing that work is when I used first() which only get the first row where my condition is true. but that way, I am only able to use one tax value. There are instances where I have two items with the same order_id (when we have different products in a cart). They come into the database with same order_id. So, I am now looking for a way to pull all rows with same order_id and then get the sum of the tax column.
if ($request->status == 'cancelled' && $order->payment_status == 'paid') {
$commissionHistoriesnow = \App\Models\CommissionHistory::where('order_id', $request->order_id)->get();
$total__ = 0;
foreach ($commissionHistoriesnow as $key => $commissionHistorynow) {
if($commissionHistorynow->admin_commission != null) {
$total__ += $commissionHistorynow->admin_commission;
}
}
$seller = Seller::where('user_id', $commissionHistoriesnow->seller_id)->first();
$seller->admin_to_pay += $total__;
$seller->save();
}
You can use the sum method of the Builder to get a sum of that column for you without having to retrieve all the records and iterate them:
$total = CommissionHistory::where('order_id', $request->order_id)
->sum('admin_commission');
Additional:
Also, you could use the increment method on the Model to increment the 'admin_to_pay' field and update it in the database (which would fire Model events):
$seller->increment('admin_to_pay', $total);
If you are not worried about events and there is only the one record by this condition you could call increment on the builder itself to update the record you are querying for:
Seller::where('user_id', $commissionHistoriesnow->seller_id)->increment('admin_to_pay', $total);
Laravel 8.x Docs - Queries - Running Database Queries - Aggregates sum
Laravel 8.x Docs - Eloquent - Retrieving Single Models / Aggregates - Retrieving Aggregates sum
Laravel 8.x Docs - Queries - Update Statements - Increment & Decrement increment

laravel counting two different table, after getting two values convert in single value

laravel counting two different table, example(table-A,table-B) after counting we get two different values that two values example(table-A=10,table-B=10) how to sum that value example(table-A=10 + table-B=10), total value 20
and pass that in view
public function index()
{
$table-A = A::all()->count();
$table-B = B::all()->count();
return view('home',compact('table-A','table-B'))
}
Do this that way:
public function index()
{
$tableA = A::all()->count();
$tableB = B::all()->count();
$sum = $tableA + $tableB;
return view('home',compact('tableA','tableB', 'sum'))
}

How to perform a calculation on a row basis and SUM on laravel

I have a situtaion where I have data in two columns in a table, which need to be multiplied on a row basis. Then each value from the multiplication has to be added to provide a net result
I tried this but it does not work
public function getCampaignStats($item)
{
$query = CampaignStats::where('item',$item);
foreach($query as $q) {
$q->p_c;
$q->caa;
dd($q->p_c);
}
return $query;
}
I get this exception when i try to do this
Object of class Illuminate\Database\Eloquent\Builder could not be converted to string
Is there a better way to do this foreach loop in laravel
You can use raw queries for such a case and do the math within your query. Have a look at the docs:
https://laravel.com/docs/5.4/queries#raw-expressions
https://laravel.com/docs/5.4/queries#where-exists-clauses

Doctrine 2 - Get total when using limit via repository

I'm new to Doctrine, and I just could not find a way to get the total number of results when using limit with Criteria (via setMaxResults function) in the EntityRepository::matching method.
In my repository (not an extend of EntityRepository), I'm using the following (I know this is not the optimal code, it is used just to learn Doctrine):
public function getAll($query = null) {
if ($query instanceof Criteria) {
$users = $this->em->getRepository('App\Entities\User')->matching($query)->toArray();
} else {
$users = $this->em->getRepository('App\Entities\User')->findAll();
}
return $users;
}
Now lets say that the Criteria is defined like so:
$query = Criteria::create();
$query->where(Criteria::expr()->contains('username', 'ron'));
$query->setMaxResults(10);
And there are actually more than 10 users that match that.
How can I get the total number of the users that match the criteria?
If you set maxResults to 10, you get 10 results ;).
Why don't you call getAll() to get all results and apply the MaxResults later?
//search for Ron's
$query = Criteria::create();
$query->where(Criteria::expr()->contains('username', 'ron'));
//check how many Ron's your database can find
$count = $repo->getAll($query)->count();
//get the first 10 records
$query->setMaxResults(10);
$users = $repo->getAll($query);

Counting total distant relationships in Laravel (eager loading?)

I'm having issues getting a proper count total with my Laravel model.
Model Structure
User
Item
ItemLike
A user can have multiple Items, and each of these Items can have multiple ItemLikes (when a user 'likes' the item).
I can easily get the individual ItemLike counts when using an Item model:
return $this->itemLikes()->count();
But I can't figure out how to get the total # of ItemLike's a User has across all the Item's he owns.
EXAMPLE
User A has 3 Items. Each Item has 5 ItemLike's, for a grand total of 15.
I tried using eager loading on the User model like this:
return $this->items()->with('itemlikes')->get()->count();
But that returns 3 (the # of Items)
These are the queries it ran, which appears like the second query is the one I want, yet every way I try it I still get 3 instead of 15
select * from `items` where `items`.`user_id` = '1000'
select * from `item_likes` where `item_likes`.`item_id` in ('1000', '1001', '1002')
After suggestions from others I found 2 solutions to get the result.
Using whereIn:
$itemViewCount = ItemView::
whereIn('item_views.item_id', $this->items()->lists('id'))
->count();
return $itemViewCount;
2 queries for a total of 410μs
Using join:
$itemViewCount = $this->items()
->join('item_views', 'item_views.item_id', '=', 'items.id')
->count();
return $itemViewCount;
2 queries for a total of 600μs
Isn't it just a case of creating a method that would return the number of items for the model. e.g.:
#UserModel
public function nbLikes()
{
$nbLikes = 0;
foreach($this->items() as $item) {
$nbLikes += $item->itemLikes()->count();
}
return $nbLikes;
}
And then User::nbLikes() should return the piece of data you are looking for?
try this:
$query="select count(il.id) from item_likes il,item itm where il.item_id=itm.id and tm.user_id=1000";

Categories