Ordering by updated_at per group - laravel

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.

Related

Filter record through dates not working laravel

I have a expiry_date (type=date) column in my table
$currentDate = date('Y-m-d');
$Data = Post::whereDate('expiry_date','<=',$currentDate)->where(['status' => 'active'])->orWhere(['p_id' => 3])->select('id','title','status','p_id','expiry_date')->orderBy('id', 'DESC')->get();
i want to filter data if current date is greater than expiry date then those record should not be shown but in my scenario i'm still getting record.
Any solution Thanks.
You must group orWhere clause in closure. Grouping in closure is like () in real query.
$Data = Post::whereDate('expiry_date','<=',$currentDate)
->where(function($query){
return $query
->where(['status' => 'active'])
->orWhere(['p_id' => 3]);
})
->select('id','title','status','p_id','expiry_date')
->orderBy('id', 'DESC')
->get();
But, because I don't know your project - i may wrong with grouping.

Laravel Query Builder - group by and sum

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);

How to sorting by current login user first in Laravel?

Below code is to divide list view by permission in the Job table.
public function index(Request $request)
{
$user_name = Auth::user()->name;
$jobs = Job::orderBy('created_at', 'desc') //#default
->where('is_trash', '==', 0)
->paginate(15);
if(!Auth::user()->hasPermissionTo('Admin')){ //check by permission
$jobs = Job::orderBy('created_at', 'desc')
->where('user_name', '=', $user_name)
->where('is_trash', '==', 0)
->orderby('updated_at', 'desc')
->orderBy('deleted_at', 'desc')
->paginate(15);
}
return view('jobs.index')
->with('jobs', $jobs);
}
For example, current login user name is C and there has A, B, D users.
Then I wish to show list as
------------------------------
C
A
B
D
------------------------------
How do I sort the currently logged in users first in the list?
Thank you in advance.:)
To place a row above all other rows and then order the remaining rows in ascending / descending order you need to do something like this SELECT * FROM table ORDER BY field = value ASC
So for your query something like this should work
$user_name = Auth::user()->name;
$jobs = Job::orderByRaw("user_name = ':name' ASC", ['name' => $user_name])
->orderBy('created_at', 'desc')
->where('is_trash', '==', 0)
->paginate(15);
I'm not entirely sure which query you wish to order and by which field but this example should give you enough to adapt on. It is untested but if :name isn't working as per the example try wrapping the query in \DB::raw() to add the binding $user_name.
You could use collections for that. Just tested, works perfectly:
list($user, $collection) = $collection->partition(function($user) {
return $user->id === auth()->id();
});
$collection = $user->merge($collection);

Laravel eloquent Query Reuse extra condition

I have a query which gives me list of total counts of different items, as:
$data = DB::table($Table1)
->join($table2,$Table1.'.id','=',$Table2.'.device_key')
->where($Table1.'.created_at', '>', $value)
->select('item', DB::raw('count(*) as total'))
->groupBy('item')
->lists('total', 'item');
now i want to fetch same data with extra condition as >where($Table1.'.status', '=', 'SUCCESS') .
how do i do that ??
I don't think you'll get away with anything nice than this.
$query = DB::table($Table1)
->join($table2,$Table1.'.id','=',$Table2.'.device_key')
->where($Table1.'.created_at', '>', $value)
->select('item', DB::raw('count(*) as total'))
->groupBy('item');
$data1 = $query->lists('total', 'rem');
$data2 = $query->where($Table1 . '.status', '=', 'SUCCESS')->lists('total, 'rem');
Use clone to copy the query object for modifications.
$query = DB::table()->where();
$clonedQuery = clone $query;
$clonedQuery->where(..);

Foreach loop not going through correctly

I have a form to mark employees' attendance that HR fill in which is looped over every current employee. I need it to show the current values where attendance is marked in the database, otherwise it should be blank.
In my controller I query the existing results:
$results = Attendance::where('Sdate', '=', date("Y-m-d", strtotime($TheDate))) ->get();
Then loop through them to get the employee details:
foreach($results as $result)
{
$contractors = DB::table('contractors') ->where('contractors.AreaPosition', '=', $department) ->where('PRN', '!=', $result->PRN) ->get(); $employees = DB::table('current_employees') ->where('current_employees.AreaPosition', '=', $department) ->where('PRN', '!=', $result->PRN) ->get(); $showEmployees = array_merge($contractors, $employees);
}
This should exclude all employees who have a record saved in attendance for that date, however it doesn't seem to be looping correctly. It will exclude some results, but not all. If I return the results variable I get the correct list of records so I know that part is working correctly.
What I'm looking to achieve in my view is something like:
#foreach($attendance as $results)
Show form where there's an existing record for this date and department
#endforeach
#foreach($employees as $employee)
Show form for all employees in this department (but should exclude results where there is a record in attendance)
#endforeach
The problem with your code is you are saving the result in a variable and not in an array.
Your solution would be to store the data in an array
foreach($results as $result)
{
$contractors[] = DB::table('contractors') ->where('contractors.AreaPosition', '=', $department) ->where('PRN', '!=', $result->PRN) ->get(); $employees = DB::table('current_employees') ->where('current_employees.AreaPosition', '=', $department) ->where('PRN', '!=', $result->PRN) ->get(); $showEmployees = array_merge($contractors, $employees);
}
Try printing contractors array and see what happens.I hope this works
This was answered for me on Laracasts.
What I needed to do was create a list of the variable to check against (employee number)
$PRNs = Attendance::where('Sdate', '=', date("Y-m-d", strtotime($TheDate)))->lists('PRN');
And then use Laravel's whereNotIn, checking against the list.
$contractors = DB::table('contractors')
->where('contractors.AreaPosition', '=', $department)
->whereNotIn('PRN', $PRNs)
->get();

Resources