Get min(date), max(date) with group by eloquent laravel - php

This query is for getting other data with the highest value of date with the group by/unique. Here I used unique in place of group by.
My question is how to get min(date) and max(date) with group by/unique.
The group by/unique is for Dataset table's date field.
I have searched for this but not getting exact solution that how to get max and min date with group by/unique in laravel eloquent.
In table structure, there are multiple entries for one code so here I used group by/unique to get one record for the code.
There can be multiple dates as 02-01-2003,01-03-2007,01-01-2019, 01-07-2018... etc. with same/ different code. If I group by with code then get onmy one record per code. So here I want to select the max date [01-01-2019] and min date [02-01-2003].
Thanks in advance.
Controller:
$datasets = Dataset::where('user_id', $user_id)
->orderBy('date','desc')
->get(['code', 'access','user_id','date'])
->unique('code');

Finally I got solution but this can not be the exact solution but as I am beginner and not getting the exact solution I do this functionality as below:
I created two different queries to get min and max values.
$min_datasets = Dataset::where('user_id', $user_id)
->orderBy('date','asc')
->get(['code', 'access','user_id','date'])
->unique('code');
$max_$datasets = Dataset::where('user_id', $user_id)
->orderBy('date','desc')
->get(['code', 'access','user_id','date'])
->unique('code');

Try to select max and min date like this:
$datasets = Dataset::select('code', 'access','user_id', DB::raw('MAX(date) as max_date'), DB::raw('MIN(date) as min_date'))
->where('user_id', $user_id)
->orderBy('date','desc')
->get()
->unique('code');

$data = DB::table('table_name')->where('user_id',$user_id)
->select('code','access','user_id','date')
->whereBetween('date', [02-01-2003, 01-01-2019])
->groupBy('unique_column')
->get()

Related

Laravel OrderBy by related table column

I have a table (A) that has a One to Many relation with another table (B).
I want to query Table A and eager load Table B with the Table A results - but I also want to sort Table A by a value in Table B.
I have tried using OrderBy in the query and also trying SortBy on the resultant collection but cannot get the Table A data to be sorted by the value found in Table B.
Example of what I have tried:
$query = ModelA::with("ModelB"])->get()->sortByDesc('ModelB.sortValue');
Keep in mind, I am only interested in the LATEST record from Table B. So I need to query Table A and sort by a value in the LATEST records of Table B.
How can I achieve this?
EDIT:
The below (as suggested by #ljubadr) works pretty close, but the issue is that there are many record in Table B which means that it doesn't reliably sort as it doesn't seem to sortby the latest records in Table B. Can I have the join return ONLY the latest record for each ID?
$query = ModelA::select('TableA.*')
->join('TableB', 'TableA.id', '=', 'TableB.col_id')
->groupBy('TableA.id')->orderBy('TableB.sortCol', 'desc')
->with(['x'])
->get();
EDIT 2:
#Neku80 answer has gotten me closest but it seems to not sort the column with the greatest accuracy.. I'm sorting a Decimal column and for the most part it is in order but in some places the items are out of order..
$latestTableB = ModelB::select(['TableA_id', 'sortByColumnName'], DB::raw('MAX(created_at) as created_at'))
->groupBy('TableA_id');
$query = ModelA::select('TableA.*')
->joinSub($latestTableB, 'latest_TableB', function ($join) {
$join->on('TableA.id', '=', 'latest_TableB.TableA_id');
})
->orderBy('latest_TableB.sortByColumnName')
->get();
For example, the ordering is like:
0.0437
0.0389
0.0247 <-- -1
0.025 <-- +1
0.0127
When I delete all rows except for the 'latest' rows, then it orders correctly, so it still must be ordering with old data...
I have found a solution:
ModelA::select('TableA.*', 'TableB.sortByCol as sortByCol')
->leftJoin('TableB', function ($query) {
$query->on('TableB.TableA_id', '=', 'TableA.id')
->whereRaw('TableB.id IN (select MAX(a2.id) from TableB as a2 join TableA as u2 on u2.id = a2.TableA_id group by u2.id)');
})
->orderBy('TableB.sortByCol')
->get();
Another alternative to order is like this:
$users = User::orderBy(
Company::select('name')
->whereColumn('companies.user_id', 'users.id'),
'asc'
)->get();
Here we are ordering in asc order by company name field.
In this article it is explained in detail.
You can simply execute a left join query:
ModelA::query()->leftJoin('model_b_table', 'model_a_table.primary_key', '=', 'model_b_table.foreign_key')->orderBy('model_a_table.target_column')->get();
This should work if you only need TableB's ID and created_at columns:
$latestTableB = ModelB::select('TableA_id', DB::raw('MAX(created_at) as created_at'))
->groupBy('TableA_id');
$query = ModelA::select('TableA.*')
->joinSub($latestTableB, 'latest_TableB', function ($join) {
$join->on('TableA.id', '=', 'latest_TableB.TableA_id');
})
->orderBy('latest_TableB.created_at')
->get();

SQL query in Laravel DB::raw() to order column and get first result

I'm trying to order a specific column in my DB::raw() select statement, I need to order the items for each day and get the first one for each day, so I'd end up with 5 results for 5 months but my error is
Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax
What am I missing?
GoogleAnalytics::where('event_category', 'Category')
->where('event_action', 'Action')
->whereDate('period_from', '>=', '2021-06-08')
->whereDate('period_to', '<=', '2021-06-08')
->select(DB::raw('DATE_FORMAT(created_at, "%Y-%m") as created_at'), DB::raw('FIRST(event_count ORDER BY created_at DESC ) as sessions'))
->groupByRaw('DATE_FORMAT(created_at, "%Y-%m")')
->orderBy('created_at', 'desc')
->get();
Some more context here, each day might have 100 entries, so there could be 3,000 entries per month, I need to get just a single entry in each day so I end up with 30 entries, and then add up those 30 result to produce a single result for that one month, so I'd end up with 5 items in my returned collection, but right now I can't seem to get DB::raw('FIRST(event_count ORDER BY created_at DESC ) as sessions') to grab the column, order it and just get the first result.
I don't think FIRST is a function at all, hence the error. If we break your problems into two you want:
One row for each day with the event_count column present. As per your comment above the column increments and you want the last value, thus you want the max value per day.
Sum the values of the event_count column, grouping by the month and year
1:
A select statement for this would look like
select date(created_at), max(event_count) from google_analytics group by date(created_at) where ...
Using the Eloquent builder it would look something like this:
$query = GoogleAnalytics::select(
DB::raw('date(created_at) as created_at'),
DB::raw('max(event_count) as sessions')
)
->where('event_category', 'Category')
->where('event_action', 'Action')
->whereDate('period_from', '>=', '2021-06-08')
->whereDate('period_to', '<=', '2021-06-08')
->groupByRaw('date(created_at)');
Note:
your where clause only looks at one date (2021-06-08)
this query will not return complete GoogleAnalytics models
2:
We can use the above $query to group the results per month:
$result = DB::table($query, 'per_day')->select(
DB::raw('date_format(created_at, "%Y-%m") as created_at'),
DB::raw('sum(sessions) as sessions')
)
->groupByRaw('date_format(created_at, "%Y-%m")')
->orderByRaw('date_format(created_at, "%Y-%m") desc')
->get();

Getting Group By value

Based on my question earlier Get Data from Array
it turns out that in only shows one record with completed SUM value.
I've been trying to add GROUP_BY clause like this:
$this->db->select('t1.act_id, t2.login, t1.cust_name, t1.act_type, t1.act_detail, t1.date_added, t1.date_modified, t1.act_notes, '
. 't3.category, t1.total_time, SUM(t1.total_time) as total')
->from('activity as t1')
->join('user as t2', 't1.user_id = t2.user_id', 'LEFT')
->join('customer as t3', 't1.cust_name = t3.cust_name', 'LEFT')
->where('t2.login', $user)
->where('MONTH(t1.date_added)', $month)
->group_by ('t1.user_id');
Unless I remove the SUM statement, the result still the same one record with complete SUM.
meanwhile if I change the GROUP_BY parameter into (t1.act_id) which is the primary key of that table, all records showing but the sum isn't (it only show SUM value of the first record only).
Any help would be appreciated. thank you.

Returning Array in mysql Select

I'm trying to group inventory results by the model and manufacturer name, display the amount of items matching and 1 result per grouping. With that said, I'd like to try and retrieve all inventory id's within the group. Wondering if this is possible... Any ideas?
FYI - I'm using Laravel, the line in question is the ->selectRaw(CambridgeID as CambridgeIDArray)
$getMatchingInventory = DB::table('inventory')
->selectRaw('*, count(*) as groupTotal')
->whereRaw("MATCH(ManufacturerNameMatch, SubCategoryNameMatch, MainCategoryNameMatch, Model_Name, Title_Override, Description_Old) AGAINST ('$final' IN BOOLEAN MODE)")
->selectRaw('CambridgeID as CambridgeIDArray')
->groupBy('Model_Name', 'ManufacturerNameMatch')
->having('Units_OnHand', '>=', '1')
->orderBy('ManufacturerNameMatch')
//->paginate(15);
->get();
try this
$getMatchingInventory = DB::table('inventory')
->select(DB::raw("GROUP_CONCAT(CambridgeID) as `CambridgeIDArray`, count(*) as `groupTotal`"))
->whereRaw("MATCH(ManufacturerNameMatch, SubCategoryNameMatch, MainCategoryNameMatch, Model_Name, Title_Override, Description_Old) AGAINST ('$final' IN BOOLEAN MODE)")
->groupBy('Model_Name', 'ManufacturerNameMatch')
->having('Units_OnHand', '>=', '1')
->orderBy('ManufacturerNameMatch')
->get();
You should be able to use GROUP_CONCAT for that, see: http://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html#function_group-concat
You can use specify output format options (e.g., SEPARATOR) and use additional string manipulation as needed within the GROUP_CONCAT.
(Fyi, using raw MySQL, at least for this question, would make it easier to parse.)

Laravel query with max and group by

I need to create a select query in Laravel 5.1 which I will have no problems creating via regular SQL and I am wondering if you could help me to write it in Laravel.
I created this query that gets all Users that have a truck, trailer and delivery_date equals a particular date (comes from $week_array). It is working, but it is missing some components
$RS = $this->instance->user()
->with(['driver.delivery' => function($query) use ($week_array) {
$query->where('delivery_date', [Carbon\Carbon::parse($week_array['date'])->toDateTimeString()]);
}])
->with(['driver.trailer', 'driver.truck', 'driver.trailer.trailerType'])->get();
I need to exclude those drivers that have MAX delivery date which equals or greater than selected delivery date in the query above. This is the normal query that I need to plug-in to laravel.
In other words, I need to convert the following query (simplified) to Laravel:
SELECT
*
FROM
USERS
INNER JOIN
DRIVERS ON DRIVERS.user_id = USERS.id
INNER JOIN
DELIVERIES ON DELIVERIES.driver_id = DRIVERS.id
WHERE
1 = 1
AND DELIVERIES.driver_id NOT IN (SELECT
driver_id
FROM
DELIVERIES
GROUP BY driver_id
HAVING MAX(delivery_date) >= '2016-05-10')
You're looking for whereHas. Try:
$date = Carbon\Carbon::parse($week_array['date'])->toDateTimeString();
$RS = $this->instance->user()
->with(['driver.delivery' => function($query) use ($date) {
$query->where('delivery_date', [$date]);
}])
->with(['driver.trailer', 'driver.truck', 'driver.trailer.trailerType'])
->whereHas('driver.delivery', function($query) use ($date) {
return $query->where('delivery_date', '>', $date);
}, '=', 0)
->get();
Also try validating the query looks right by replacing ->get() with ->toSql() and using the dd helper function.

Categories