Laravel Query Builder - group by and sum - laravel

I want to get a list of user activities.
But it should give me back only the 5 users, which have the most activities and a col with the sum of the activities ordered by sum of activities DESC.
$now = Carbon::now();
$lastWeekMonday = Carbon::now()->subWeek(1)->startOfWeek()->toDateString();
$mondayThisWeek = Carbon::now()->startOfWeek()->toDateString();
$userActivitiesLastWeek = DB::table('useractions')
->select('id', 'comment', 'created_user', 'created_at')
->where('created_at', '>=', $lastWeekMonday )
->where('created_at', '<', $mondayThisWeek )
->get();
Thanks for help!

You can use withCount Query Builder function to get the count of particular relationship.
And then you can order by that count and use the take Collection function to take desired number of items from a collection. In your case, 5.
$now = Carbon::now();
$lastWeekMonday = Carbon::now()->subWeek(1)->startOfWeek()->toDateString();
$mondayThisWeek = Carbon::now()->startOfWeek()->toDateString();
$uses = User::with('activities')
->withCount('activities')
->where('created_at', '>=', $lastWeekMonday )
->where('created_at', '<', $mondayThisWeek )
->get()
->sortByDesc('activities_count')
->take(5);

Related

Get records between two columns using range between two dates, Also search filter criteria

I want to get records that are joined between this date period (2022-02-15, 2022-08-20)
$users = User::whereDate('start_at', '>=', $startDate)
->whereDate('end_at', '<=', $endDate)
->get();
$_start_date = '2022-02-15';
$_end_date ='2022-08-20';
$users = User::where(function ($query) use ($_start_date, $_end_date) {
$query->where(function ($query) use ($_start_date, $_end_date) {
$query->whereRaw("start_date >= date('$_start_date')")
->whereRaw("end_date <= date('$_end_date')");
})
->orwhere(function ($query) use ($_start_date, $_end_date) {
$query->whereRaw("start_date <= date('$_start_date')")
->whereRaw("end_date >= date('$_end_date')");
});
})->get();
try above code this will also return between dates of start_date and end _date e.g below
$_start_date = '2022-02-18';
$_end_date ='2022-08-20';
and also works with below dates e.g
$_start_date = '2022-02-16';
$_end_date ='2022-08-18';
codes look like this in ide
You can use the whereBetween Laravel function:
$users = User::whereBetween('start_at', [ $startDate, $endDate])->get();
Note $startDate and $endDate must be instance of Carbon.
$startDate = new Carbon('paste_your_start_date')->format('Y-m-d')." 00:00:00";
Update
This would be one method to get data from two seperated columns. Example is not tested.
$start_at = Carbon::createFromFormat('Y-m-d H', '2022-02-15 0')->toDateString();
$end_at = Carbon::createFromFormat('Y-m-d H', '2022-08-20 0')->toDateString();
$users = User::whereRaw("start_at <= date('$start_at')")
->whereRaw("end_at >= date('$end_at')")
->get();
Depends on what you need exactly
User::whereDate('start_date', '>=', $startDate)->where('end_date', '<=', $endDate)->get();
or
User::whereDate('start_date', '<', $User)->whereDate('end_date', '>', $startDate)->get();
I think you want to get the records that at least one day from start_date to end_date that exists between 2022-02-15 and 2022-08-20:
$startDate = '2022-02-15';
$endDate = '2022-08-20';
$users = User::whereDate('start_at', '<=', $endDate) // where or whereDate also should work
->whereDate('end_at', '>=', $startDate)
->get();

Laravel Eloquent whereTime() shows null

I have this query to get the events after the the current time and it shows as null. I think the whereTime condition is not working or I have a typo.
$query = Model::where('id', $request->id)
->where('status_id', 1)
->whereTime('event_date', '>=', Carbon::now())
->first();
When I don't have the whereTime condition and check the results, it shows this result
$query = Model::where('id', $request->id)
->where('status_id', 1)
// ->whereTime('event_date', '>=', Carbon::now())
->first();
dd(Carbon::now()->format('Y-m-d H:i:s'), $query->event_date);
Result
"2020-04-15 20:07:43"
"2020-05-23 18:00:00"
If your date like this "2021-03-21 13:33:52" then separate date and time like below
$date = Carbon::parse($timestamp)->format('Y-m-d');
$time = Carbon::parse($timestamp)->toTimeString();
Now you got date and time separated and write query to desire model like below:
User::where('status', 1)->whereDate('created_at', '>=', $date)
->whereTime('created_at', '>', $time)->get();
Hope this will help you. This works for me

Wrong counting after grouping

Have tables with wallets and services
Service
id and name
Wallets
id service_id balance
$statistic = Wallets::leftJoin('service', 'service.id', '=', 'wallets.service_id')->select('name as label', 'balance as value')->where('balance', '>', 0)->whereYear('wallets.updated_at', $now->year)->whereMonth('wallets.updated_at', $now->month)->get();
And get result
[{"label":"Service1","value":0.0711679},
{"label":"Service1","value":0.015},
{"label":"Service2","value":0.065572},
{"label":"Service2","value":0.02},
{"label":"Service3","value":0.0206064},
{"label":"Service2","value":0.04399}]
but after ->groupBy('label'):
[{"label":"Service1","value":0.0711679},
{"label":"Service2","value":0.065572}
{"label":"Service3","value":0.0206064}]
get only first results
<?php
// If you are referring count as total balance then you can do this
$statistic = Wallets::leftJoin('service', 'service.id', '=', 'wallets.service_id')
->where('balance', '>', 0)
->whereYear('wallets.updated_at', $now->year)
->whereMonth('wallets.updated_at', $now->month)
->select(
\DB::raw('name as label'),
\DB::raw('SUM(balance) as value')
)
->groupBy('name')
->get();
// If you are referring count as total entries for each label then you can do this
$statistic = Wallets::leftJoin('service', 'service.id', '=', 'wallets.service_id')
->where('balance', '>', 0)
->whereYear('wallets.updated_at', $now->year)
->whereMonth('wallets.updated_at', $now->month)
->select(
\DB::raw('name as label'),
\DB::raw('balance as value'),
\DB::raw('count(*) as aggregate')
)
->groupBy('name')
->get();

Laravel Query Builder: How do I sort results by date - first with ascending order by future dates and then by descending order by past dates?

I have a model tasks with complete tasks with datetime in the past and upcoming tasks with datetime in the future.
While retrieving the tasks, I want to display the upcoming tasks arranged in ascending order (from now to the future) and tasks in the past in descending order (from now to the past).
public function getTasks()
{
$futureTasks = Task::whereDate('datetime', '>', Carbon::now())->orderBy('datetime', 'asc')->get();
$pastTasks = Task::whereDate('datetime', '<', Carbon::now())->orderBy('datetime', 'desc')->get();
$tasks = array_merge($futureTasks, $pastTasks);
$response = ['tasks' => $tasks];
// return...
}
I'm getting the following error:
array_merge(): Argument #1 is not an array
If I reverse the order of arguments for array_push function, I still get the same error.
public function getTasks()
{
$futureTasks = Task::whereDate('datetime', '>', Carbon::now())->orderBy('datetime', 'asc')->get();
$pastTasks = Task::whereDate('datetime', '<', Carbon::now())->orderBy('datetime', 'desc')->get();
$tasks = array_merge($pastTasks, $futureTasks);
$response = ['tasks' => $tasks];
// return...
}
And If I retrieve only the futureTasks or pastTasks without array_merge, I get the desired output.
public function getTasks()
{
$futureTasks = Task::whereDate('datetime', '>', Carbon::now())->orderBy('datetime', 'asc')->get();
$response = ['tasks' => $futureTasks];
// return...
}
What am I doing wrong here? Thanks a lot for your time.
Both the results are a collection. You can use the collection merge method.
public function getTasks()
{
$futureTasks = Task::whereDate('datetime', '>', Carbon::now())
->orderBy('datetime', 'asc')
->get();
$pastTasks = Task::whereDate('datetime', '<', Carbon::now())
->orderBy('datetime', 'desc')
->get();
$tasks = $futureTasks->merge($pastTasks);
$response = compact('tasks');
// return...
}
Since you're using the whereDate condition, you're missing all the data from the present date based on your queries. You might want to check that.

Ordering by updated_at per group

I have the following simple query to attempt to get the last updated row per module:
$distincts = SerialNumber::where('company_id', Auth::user()->active_company_id)
->groupBy('module')
->orderBy('updated_at', 'desc')
->get();
This doesn't work the way I want it to. Each row in the module group will not be ordered by updated_at (which is a datetime stamp).
How can I use orderBy for each row in a group? Thanks for reading!
The following works, but is a very bad solution:
$distincts = array();
$modules = SerialNumber::select('module')
->where('company_id', Auth::user()->active_company_id)
->groupBy('module')
->pluck('module');
foreach ($modules as $mod) {
$se = SerialNumber::where('company_id', Auth::user()->active_company_id)
->where('module', $mod)
->orderBy('updated_at', 'desc')
->first();
$distincts[] = $se;
}
What you need is a subquery:
$query = SerialNumber::orderBy('updated_at', 'desc')->getQuery();
$distincts = DB::table(DB::raw("(". $query->toSql() . ") as subQuery"))
->where('company_id', Auth::user()->active_company_id)
->groupBy('module')
->get();
This makes that you get only the latest records in group.

Resources