Laravel multiple count in 1 Query - php

Im new to this Framework, i dont know how to optimize it using db::raw count and aliases and display it to my blade.php using #foreach
im trying to optimize my code, my goals is to count pallet_conditions and store it to my aliases, i dont want to count it one by one like what i did on this code
this is my code not optimize:
//computing the total rapairable
$repairable_total = DB::table('liip_psrm_items')
->where('psrm_items_id', '=' , $psrm_maintenance->id)
->where('pallet_condition', '=', 1)
->count();
//REPAIRABLE
//computing the total good pallets
$good_total = DB::table('liip_psrm_items')
->where('psrm_items_id', '=' , $psrm_maintenance->id)
->where('pallet_condition', '=', 0)
->count();
//GOOD
this is the code, what i wanted to learn. just to minimize, and use aliases
$result = DB::table('liip_psrm_items')
->select(DB::raw('COUNT(liip_psrm_items.pallet_condition = 0 ) AS condition_1',
'COUNT(liip_psrm_items.pallet_condition = 1 ) AS condition_2'))
->where('psrm_items_id', '=' , $psrm_maintenance->id)
->get();

You can't use single query for two different results, which has totally opposite conditions.
Case 1. You are trying to count the items where pallet_condition = 1;
Case 2. You are trying to count the items where pallet_condition = 0;
Now you want to merge these two cases into single query, which is impossible...
So, For these two cases, you have to use either separate queries ( what you did already )
or you can use single query to grab all the items and then use PHP to separate them.
Like:
$total_items = DB::table('liip_psrm_items')
->where('psrm_items_id', '=' , $psrm_maintenance->id)
->get();
$repairable_count = count(array_filter($total_items, function($item){
return (bool)$item->pallet_condition;
}));
$good_count = count(array_filter($total_items, function($item){
return !(bool)$item->pallet_condition; //just inverse of the above condition
}));
i hope this might help.

To count at multiple condition I used this approach
$lastMonthInvoices = Invoice::select(DB::raw("(COUNT(*)) as count"), DB::raw('SUM(total) as total'),'status')
->whereDate('created_at', '>', Carbon::now()->subMonth())
->groupBy('status')
->get();
i got the result with groupBy Status and in each group total number of records as count & also their sum as total
these two snaps are of one query result

You can, first group by, then get count
Like :
DB::table('liip_psrm_items')
->groupBy('pallet_condition')
->select('pallet_condition', DB::raw('count(*) as total'))
->get();

Try to pass a closure like so:
$results = DB::table('liip_psrm_items')
->where('psrm_items_id', '=' , $psrm_maintenance->id)
->where(function($query){
$query->where('pallet_condition', 1)
->orWhere('pallet_condition', 0);
})->count();

Related

Laravel DB Query Using Select and Count together

I want to use count and sum together on DB Query not sure how to go about it. I've tried several combinations but keep getting an error. I know I can just use a raw query but would like to learn how to use it correctly
Working:
DB::select('SELECT count(*) AS order_count, sum(total_including_vat)
AS orders_total FROM orders WHERE user_id =' .$userProfile->id);
Not Working
DB::table('orders')->where('user_id', '=', $userProfile->id)->count()->Sum();
count same as aggregates returns single value so
// you try to call method sum on number and it fails
DB::table('orders')->where('user_id', $userProfile->id)->count()->sum();
you can make two requests to get sum and count but its not a good idea, or get data in collection and let it do the math
// not a good idea
//$count = DB::table('orders')->where('user_id', $userProfile->id)->count();
//$sum = DB::table('orders')->where('user_id', $userProfile->id)->sum('total_including_vat');
//collection way
$orders = DB::table('orders')
->where('user_id',$userPorfile->id)
->get(['id', 'total_including_vat']);
$result = [
'order_count' => $orders->count(),
'orders_total' => $orders->sum('total_including_vat')
];
or the same result as for your working example with mix raw expressions
$result = DB::table('orders')
->where('user_id', $userProfile->id)
->selectRaw('count(1) as order_count, sum(total_including_vat) as orders_total')
->first();

Laravel change relationship where clause if not rows are returned

I have the following query in my controller.
$items = Item::with(['subitems' => function($query) {
$query->where('language_id', '=', 1);
}])->get();
This is correctly getting me all items including subitems that have a language id of 1.
There are two things I would like to do with this though
Firstly, I need to return all subitems that have a distinct 'ref_id' value.
Secondly, I would like to give preference to the language id 1 but if none exist, use any language id.
So for example, I know this code won't work, but the sort of thing I am looking for is:
$items = Item::with(['subitems' => function($query) {
$subItems = $query->where('language_id', '=', 1)
->where('ref_id', 'is', 'distinct');
if($subItems->count() <= 0) {
$subItems = $query->where('ref_id', 'is', 'distinct');
}
}])->get();
Is this possible or is it a bit too complicated for Query Builder? Even if one of the two requests was possible, that would be great.
Try this:
$items = Item::with(['subitems' => function($query) {
$join = Subitem::select('ref_id', DB::raw('MIN(language_id) language_id'))
->groupBy('ref_id');
$sql = '(' . $join->toSql() . ') subitems_distinct';
$query->join(DB::raw($sql), function($join) {
$join->on('subitems.ref_id', 'subitems_distinct.ref_id')
->on('subitems.language_id', 'subitems_distinct.language_id');
});
}])->get();
We can use the fact that your preferred language_id is the lowest value and select the minimum.

Laravel Model Using Or in where Condition?

I want to get the template from user_webhook table in my database.In WHERE condition i am checking user_id,app_id and if either notify_admin or notify_customer value is 1 in user_webhook table.I am using query..
$templates= $this->where('notify_admin',1)
->orwhere('notify_customer',1)
->where('user_webhooks.user_id',$user_id)
->where('user_webhooks.app_id',$app_id)
->select( 'webhooks.id as webhook_id','webhooks.app_id','webhooks.topic','webhooks.type','webhooks.action',
'webhooks.sms_template','user_webhooks.id','user_webhooks.notify_admin',
'user_webhooks.notify_customer','user_webhooks.user_id','user_webhooks.sms_template_status',
'user_webhooks.sms_template as sms'
)
->join ('webhooks',function($join){
$join>on('webhooks.id','=','user_webhooks.webhook_id');
})
->get()
->toArray();
when i get query using DB::getQueryLog(), I found the query seems Like
select `telhok_webhooks`.`id` as `webhook_id`, `telhok_webhooks`.`app_id`,
`telhok_webhooks`.`topic`, `telhok_webhooks`.`type`, `telhok_webhooks`.`action`,
`telhok_webhooks`.`sms_template`, `telhok_user_webhooks`.`id`,
`telhok_user_webhooks`.`notify_admin`, `telhok_user_webhooks`.`notify_customer`,
`telhok_user_webhooks`.`user_id`, `telhok_user_webhooks`.`sms_template_status`,
`telhok_user_webhooks`.`sms_template` as `sms` from `telhok_user_webhooks`
inner join
`telhok_webhooks` on `telhok_webhooks`.`id` = `telhok_user_webhooks`.`webhook_id`
where `notify_admin` = ? or `notify_customer` = ? and `telhok_user_webhooks`.`user_id`
= ? and `telhok_user_webhooks`.`app_id` = ?
The result of query giving result of all app_id and user_id.
So Please tell me use of OR in where condition.
Thanks in advance.
You may chain where constraints together as well as add or clauses to the query. The orWhere method accepts the same arguments as the where method:
$users = DB::table('users')
->where('votes', '>', 100)
->orWhere('name', 'John')
->get();
Advanced usage:
Usere::where('id', 46)
->where('id', 2)
->where(function($q) {
$q->where('Cab', 2)
->orWhere('Cab', 4);
})
->get();
The whereIn method verifies that a given column's value is contained within the given array:
$users = DB::table('users')
->whereIn('id', [1, 2, 3])
->get();
More: https://laravel.com/docs/5.5/queries
Change
->where('notify_admin',1)
->orwhere('notify_customer',1)
to
->where(function($q){
$q->where('notify_admin',1)
->orWhere('notify_customer',1);
})
Without this, the orWhere will compare to all other wheres in your query instead of just comparing those two columns

Count number of row using mysql query in laravel

I trying to use Laravel count() function to get the count of row. I have below code to count the number of row of 2 join table.
Example 1:
$row = DB::table('log_user_login')
->select(DB::raw('log_user_login.Password as LogPassword'), 'user.*')
->join('user', 'log_user_login.Username', '=', 'user.Username')
->where('log_user_login.LoginSession', '!=', '')
->groupBy('user.ID')
->get();
$count = sizeof($row);
Example 2:
$count = DB::table('log_user_login')
->select(DB::raw('log_user_login.Password as LogPassword'), 'user.*')
->join('user', 'log_user_login.Username', '=', 'user.Username')
->where('log_user_login.LoginSession', '!=', '')
->groupBy('user.ID')
->count();
When I echo $count form Example 1, the number of $count is 15415. But $count of Example 2 return me 89. May I know why this happen and how can I get the number of row without using the get()?
Example 1 displays the sizeof array in bytes, but example 2 displays total count returned by table.
So, best way to get total count is using ->count() as done in example 2.
Hope you got your answer.
Please try it.
$row = DB::table('log_user_login')
->select(DB::raw('log_user_login.Password as LogPassword'), 'user.*')
->join('user', 'log_user_login.Username', '=', 'user.Username')
->where('log_user_login.LoginSession', '!=', '')
->groupBy('user.ID')
->get();
echo $count = count($row);
Do not use sizeof(). So many time its return amount of memory allocated.
Use count() instead of sizeof().

Laravel Queries

I have 2 tables items and branch_item
I need to optimize and query this,
$test2 = DB::table('items')
->join('branch_item', 'items.id', '=', 'branch_item.item_id')
->select('items.minimum', 'branch_item.item_quantity')
->where('branch_item.branch_id',9)
->where('branch_item.item_quantity','<' ,'items.minimum')
->get();
return $test2;
What I need is to query the items that is below in minimum in quantity of certain branch.
I can do this using foreach but it loads so slow so I think I need to use join tables.
$test2 = DB::table('branch_item')
->join('items', 'branch_item.item_id', '=', 'items.id')
->select('branch_item.id','items.id','items.minimum', 'branch_item.item_quantity')
->where('branch_item.branch_id',9)
->having('items.minimum', '>' ,'branch_item.item_quantity')
->get();
Our team debugs it already, what the problem is we use Where instead of Having,
There is a big difference between having and where.

Categories