Group by month or week with Laravel eloquent - php

I have a project which has management of my investments, that is, it takes my daily statement and saves it in my project so that I can see how much it is yielding, in summary I have a table that are these values daily, I can already generate the information separated by day and it works perfectly (in fact it is a little more complex than this what I do but the basis is this);
But now it's getting bad to see when I get a very large date range for example 1 year, it lists every day, I wanted a way to group by month or week,
Thanks in advance for any help.
$rows = AtivosExtrato::select('titulo_id', DB::raw('SUM(valor_bruto_atual) AS valor'), 'data_imports.data_import as created_at')
->join('titulos','titulo_id', '=', 'titulos.id' )
->join('representantes','representante_id', '=', 'representantes.id' )
->join('data_imports','data_import_id', '=', 'data_imports.id' )
->where('user_id', Auth::user()->id)
->whereBetween('data_imports.data_import', [$request->input('start_date'), $request->input('end_date')])
->groupBy('titulos.nome_titulo')
->groupBy('data_imports.data_import')
->orderBy('data_import')
->orderBy('titulos.nome_titulo')
->get();
Briefly explaining what each eloquent information is:
AtivosExtrato: model where the daily income information is;
1) join: foreign table for the names of the titles
2) join: foreign table for the broker's name
3) join: table that saves the date of the import and relates to the id in the asset tableExtrato, it has a function to reduce the weight in the time of the searches and to gain performance.
where: limiting to the user in question
WhereBetween: limiting to date range
1) groupBy: Grouping by titles
2) groupBy: grouping by date of import
Table structure:
ativos_extrato
ativos_extratos foreign key
data_imports
Solution:
$rows = AtivosExtrato::select(
'titulo_id',
DB::raw('SUM(valor_bruto_atual) AS valor'),
'data_imports.data_import as created_at',
DB::raw('WEEK(data_imports.data_import) AS weeknumber')
)
->join('titulos','titulo_id', '=', 'titulos.id' )
->join('representantes','representante_id', '=', 'representantes.id' )
->join('data_imports','data_import_id', '=', 'data_imports.id' )
->where('user_id', Auth::user()->id)
->whereIn('ativos_extratos.data_import_id',
DataImport::Select(DB::raw('max(ID)'))
->whereBetween('data_import', [$request->input('start_date'), $request->input('end_date')])
->groupBy(db::raw('Week(data_import)')) )
->whereBetween('data_imports.data_import', [$request->input('start_date'), $request->input('end_date')])
->groupBy('titulos.nome_titulo')
->groupBy('weeknumber')
->orderBy('data_import')
->orderBy('titulos.nome_titulo')
->get();

Add DB::raw(WEEK(data_imports.data_import) AS weeknumber) and then replace ->groupBy('data_imports.data_import') with ->groupBy('weeknumber') and the same with MONTH() function if you want to group by month: add another select column DB::raw(MONTH(data_imports.data_import) AS monthnumber) and replace ->groupBy('data_imports.data_import') with ->groupBy('monthnumber'). So the whole Eloquent query with week grouping would be:
$rows = AtivosExtrato::select('titulo_id', DB::raw('SUM(valor_bruto_atual) AS valor'), 'data_imports.data_import as created_at', DB::raw('WEEK(data_imports.data_import) AS weeknumber'))
->join('titulos','titulo_id', '=', 'titulos.id' )
->join('representantes','representante_id', '=', 'representantes.id' )
->join('data_imports','data_import_id', '=', 'data_imports.id' )
->where('user_id', Auth::user()->id)
->whereBetween('data_imports.data_import', [$request->input('start_date'), $request->input('end_date')])
->groupBy('titulos.nome_titulo')
->groupBy('weeknumber')
->orderBy('data_import')
->orderBy('titulos.nome_titulo')
->get();

Related

Laravel Eloquent grab duplicates (2 or more results)

So I have the following query, which is working:
Expense::select('amount', 'date', DB::raw('COUNT(*) as `count`'))
->groupBy('amount', 'date')
->havingRaw('COUNT(*) > 1')
->get();
This is to grab all expenses that are potential duplicates (same amount and same date). However, I want to grab everything, not only the amount and date. The following is not working:
return Expense::select('name', 'amount', 'date', DB::raw('COUNT(*) as `count`'))
->groupBy('amount', 'date')
->havingRaw('COUNT(*) > 1')
->get();
This will give me this error:
SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #1 of the SELECT list is not in the GROUP BY clause and contains a nonaggregated column
I have many more fields for an Expense that I want to list in my view, most importantly of course the name, but also the slug so I can link to each potential duplicate, etc.
Also, the second "issue", but not the most important one, is that with the above query, all expenses are returned in one collection. They are not grouped by date for example.
The most desirable would be to have the results somewhat like this. All potential duplicates should be grouped by the date so I can do something like this in my view:
#foreach($duplicates as $date => $expenses)
#foreach($expenses as $expense)
{{ $date }}
// List all expenses for that date.. etc.
Question 1: How would I make the above query work with all database fields, not only the date and amount?
Question 2: How would I be able to grab the potential duplicates and group them by date so I can loop over the dates and the expenses like in the above example?
Always handle column properly when doing grouping
e.i. you can specify all the fields you want to select in groupBy
// database query
$expenses = Expense::select(['amount', 'date', 'name', 'slug'])
->selectRaw('count(*) AS count')
->havingRaw('count > 1')
->groupBy(['amount', 'date', 'name', 'slug'])
->get();
// Another date grouping done in collection
return $expenses->groupBy('date');
or something like combing columns that belongs to your desired grouping
return Expense::select('date')
->selectRaw('group_concat(name) as names') // comma separated names belongs to the group
->selectRaw('group_concat(amount) as amounts') // comma separated amounts belongs to the group
->selectRaw('group_concat(slug) as slugs')// comma separated slugs belongs to the group
->selectRaw('count(*) AS count')
->havingRaw('count > 1')
->groupBy('date')
->get();
EDIT
If you only want to group them by date and still have the actual rows of duplicate, you can just add another select statement to count for date duplicate without grouping them by date in your query, and do the date grouping in collection.
e.i.
$expenses = Expense::select( ['amount', 'date', 'name', 'slug'] )
->selectRaw('(SELECT COUNT(date) FROM expenses t1 WHERE t1.date = expenses.date ) as duplicates')
->havingRaw('duplicates > 1')
->get();
return $expenses->groupBy('date');
Then the output should have another column duplicates which has the number of duplicate each date has and still has all the rows for duplicate dates

How to use the Larave DB Facade to get the first record with a date close to a particular date

I am trying to get the first transaction that was recorded close to a particular date using the Laravel 8 DB Facade.
I have tried to use it in the following manner
$lastest_transaction = DB::table($targetTable)
->where('date', '<=', date('F'))
->where('id', '=', $client->id)
->where('branch', '=', session('branch'))
->get();
but it's not giving me the correct transaction.
In order to get the record closest to the date, you can sort by the date in descending order, which would make the first record the "largest" date that's less than or equal to what you are searching for:
$lastest_transaction = DB::table($targetTable)
->where('date', '<=', date('F'))
->where('id', '=', $client->id)
->where('branch', '=', session('branch'))
->orderBy('date', 'DESC') // Order by the date in descending order
->first(); // Get the first record

Sum of column in where clause in laravel eloquent

I have a FamilyMember model and a SubscriptionCharge model, SubscriptionCharge store charges of multiple months of each family member.
I have to select members whos sum of charges greater than a specific amount.
$members=FamilyMember::whereHas('subscription_charge', function ($qq) {
$qq->where(); // how to check sum of column 'amount' in where
})->get();
How to check the sum of column 'amount' in a where condition
Based on your comment, Updated Answer
$memeber = FamilyMember::query()
->join(DB::raw('("SELECT subscription_charge.family_member_id, SUM(subscription_charge.amount) as total_charges FROM subscription_charge GROUP BY subscription_charge.family_member_id HAVING SUM(subscription_charge.amount) >
AMOUNT_YOU_WANT") as sub_table'), function($join) {
$join->on('sub_table.family_member_id', '=', 'family_member.id');
})->get();
Note: Not tested
I think you might be able to do something like this. (I'm at the airport so unable to test it.)
$members=FamilyMember->join(DB::raw('(SELECT family_member_id, SUM(amount) AS sum_of_charges
FROM subscription_charge
WHERE family_member_id = x
GROUP BY family_member_id
// (or HAVING family_member_id = x ?)
) charges'),
function($join)
{
$join->on('FamilyMember.id', '=', 'charges.family_member_id');
})
->select(
'FamilyMember.id',
'charges.sum_of_charges'
)
->where('sum_of_charges', '>', 'Y')
})->get();

Laravel append data count to database object

Hello i have this function
public function readData(){
$TableB1 = \DB::table('users')
->join('group_user', 'users.id', '=', 'group_user.user_id')
->join('groups', 'groups.id', '=', 'group_user.group_id')
->join('meetings', 'users.id', '=', 'meetings.owned_by_id')
->select(
'users.name as name',
'group_user.user_id as id',
'groups.name as groupname',
)
->get();
foreach ($TableB1 as &$data){
$meetings = \DB::table('meetings')
->where('company_id', 1)->where('owned_by_id', $data->id)
->where(\DB::raw('MONTH(created_at)'), Carbon::today()->month);
echo $meetings->count();
}
return $TableB1;
}
i retrieve some data from database and return them and use AJAX Call to use them later
The problem is i have a table called users and table called meetings
i want to know how many meetings every user done everyday
so to do this i made a for each to take the user_id and use it to get the count
of meetings done by each user
for example in meetings table i have a owned_by_id field which have the user_id
so what the code does if it found for example if owned_by_id(6) repeated in
meetings table 4 times it will return 4
but this is what i get in the browser
instead what i want to get is something like this
im using Laravel 5.7 and sorry i know my question is unclear this is the 1st time i have ever asked question on stackoverflow
Image
If you want count of meetings then you may use laravel eloquent method with is: withCount();
Like this:
$users = User::with('meetings')->withCount('meetings')->get();
If you will do this then you will get meetings_count with your user object.
And if you have still any doubt you may refer following link:
https://laravel.com/docs/5.8/eloquent-relationships
Thnak you!
You could add a new column in the select() using the COUNT SQL statement:
->select(
'users.name as name',
'group_user.user_id as id',
'groups.name as groupname',
\DB::raw('(
SELECT COUNT(meetings.id) FROM meetings GROUP BY meetings.owned_by_id
) as meetings')
)

Laravel query failed using function query

I am trying to get sum of amount of all users group by month.But if I add sum then query not work.It return amount log as blank array But without sum query return all logs data as monthly.
My query
$reports = $user->whereHas('groups', function ($query) use($acceptedGroup) {
$query->whereIn('groups.name',$acceptedGroup);
})->with(
array(
'amountLogs' => function($query) use($year){
$query
->select(
DB::raw('sum(amount) as total')
)
->whereYear('created_at','=', $year)
->groupBy(DB::raw("MONTH(created_at)",'user_id'))->get();
})
);
If I remove
->select(
DB::raw('sum(amount) as total')
)
Then query works
If you creating a specific select on a relationship in your query, you also need to include the foreign key to the related table (in your case, probably the users table)
->select(
'user_id',
DB::raw('sum(amount) as total')
)
This allows Eloquent to relate the records after loading from the database.

Categories