Laravel Eloquent - Get a record every hour - laravel

I have a table that stores statistics every 3 minutes with a cron job.
I want to display a chart with this data but I want the chart to have an interval of 1 hour otherwise it looks ugly as hell and is too much resource demanding.
The table has the created_at and updated_at columns.
How can I do this with eloquent?
EDIT: I want to query the records from the last 24 hours but that gives me around 480 records which is too much for a chart. I'd like to have only 24 records instead (one for every hour).
Thanks for your help!

Thanks Tim!
For anyone reading through this later, here is the solution: https://laracasts.com/discuss/channels/laravel/count-rows-grouped-by-hours-of-the-day
Model::where('created_at', '>=', Carbon::now()->subDay())->get()->groupBy(function($date) {
return Carbon::parse($date->created_at)->format('h');
});

This will allow you to get data 1 hours ago base on current time.
//Get all data for the day
$all_data = Model::where('created_at','>=',Carbon::today()->get());
//Recursive to groupBy hours
$i=1;
while ($all_data->last() != null)
{
$hourly_data = Model::where('created_at','>=',Carbon::today()->addHours($i))->get();
$all_data= $all_data->merge($hourly_data);
$i++
}
return $all_data;

Related

One eloquent query with whereIn clause with more than 3000 elements works but another one with the same elements and format doesn't

Hello and thank you beforehand for your help.
I've been hitting my head against a wall with this problem for a few days now so decided to ask here. I have two queries in Laravel, one grouping totals by week, and the other by month. The week one works fine but for some reason the month one doesn't, the only difference in essentially the query is that the weekly one is calculated yearly but in a different period (starting in week 48 of last year and ending in week 47 of this year), while the monthly is just the real year. The only other difference is that the week query is inside an if to show the right thata in those final weeks of the year.
$weeklySalesLastYear = Invoice::where(function ($query) use ($year, $client_ids){
$query->where('year', $year-2)->where('week', '>=', 48)->whereIn('client_id', $client_ids);
})->orWhere(function($query) use ($year, $client_ids){
$query->where('year', $year-1)->where('week', '<=', 47)->whereIn('client_id', $client_ids);
})->groupBy('week')->selectRaw('sum(total) as total, week')->get();
That is my weekly query which works perfectly.
$sortedMonthlySalesLastYear = DB::table('invoices')
->where('year', $year-1)->whereIn('client_id', $client_ids)
->groupBy('month')->selectRaw('sum(total) as total, month')->get();
And this is my monthly query which doesn't work. I know that there is an issue with whereIn clauses in eloquent where they don't accept a big number of elements for some reason, but I'm wondering why one works and not the other one and if there is a solution to it. I also want it to be an object, I've tried using a raw query but it throws an array instead, and I would rather avoid using that. This is the one that worked.
$sortedMonthlySalesLastYear = DB::select( DB::raw("SELECT SUM(total) AS total, month FROM invoices WHERE year = '$lastYear' AND client_id IN ($client_ids_query) GROUP BY month"))
Schema::create('invoices', function (Blueprint $table) {
$table->id();
$table->string('month');
$table->integer('year');
$table->integer('week');
$table->integer('client_id')->index()->unsigned();
$table->integer('product_id')->index()->unsigned();
$table->integer('quantity');
$table->float('total');
$table->double('discount');
});
This is what my invoices migration looks like, the client relates to the user and that's how I get the arrays.
This is what the monthly query returns:
[2022-05-02 23:40:05] local.INFO: monthly sales:
[2022-05-02 23:40:05] local.INFO: []
And this is what the weekly one returns (it's a larger set
but this is a sample of what it throws to show its working.)
[2022-05-02 23:42:42] local.INFO: weekly sales:
[2022-05-02 23:42:42] local.INFO:
[{"total":536190.4699999997,"week":1},
{"total":568192.6700000003,"week":2},
{"total":1613808.48,"week":3},
{"total":878447.3600000001,"week":4}...]
An example of a few invoices I'm trying to process is this (there are more than 130K invoices in the database):
I'd appreciate any help and if you have a solution to this, I mostly just prefer to stay using eloquent for the code to look cleaner. Thank you.
I also have to add that the query returns the expected values if I sign in with any other user since the range of clients they have is much smaller.
I figured it out after so long. The only thing I did was implode the client_ids collection and then explode it into an array. No idea why it does accept a big array and not a big collection, and still no idea about the discrepancy between the queries.
$clients = Client::where('user_id', $user_id)->get('id');
$imp = $clients->implode('id', ', ');
$client_ids = explode(', ', $imp);
All queries work with that.

Laravel, how to delete all records but the first one of that day

So I have a table to log profile followers every 10 minutes to keep a record of the increase/decrease.
However after the current day I only need to keep the last record of that day. Is there a simple way in Laravel to delete all records a part from the last one recorded every day.
I've tried searching and searching but comes up with nothing and feel like I'm going to create something overly complicated to accomplish this.
You'd need a query like this.
DELETE
FROM logs
WHERE id IN (
SELECT id
FROM logs
WHERE created_at BETWEEN 2022-02-28 00:00:00 AND 2022-02-28 23:59:59
ORDER BY created_at DESC
OFFSET 1
)
Assuming you have a date variable, you could make the query like this using the whereDate method:
$date = '2022-02-28'; // Y-m-d format. This is important.
DB::table('logs')
->whereIn('id', function ($sub) use ($date) {
$sub->select('id')
->from('logs')
->whereDate('created_at', $date)
->orderByDesc('created_at')
->offset(1);
})
->delete();

How to subtract one minute from column in mysql database in laravel?

I am Trying to subtract 1 minute from duration column through update query but it is not working. Duration field is of type time.
I try to use minus sign with new value but it is not working.
public function index()
{
$current = Carbon::now('Asia/Karachi');
Sale::where('date','=',$current->toDateString())
->where('time','<=',$current->toTimeString())
->update(['duration' => '- 00:01:00']);
}
I want to subtract one minute with help of this query.
Can you use DATE_SUB?
Something like
$object->update(['duration' => DB::raw('DATE_SUB(duration, INTERVAL 1 MINUTE)')])
I don't have a laravel instance in front of my, but that's how I'd write the SQL query and I think that's right based off my laravel memory.

Laravel, Carbon. Get count of hours for a specific month between dates

How to get the number of hours referring only to the one month between 2 dates?
For example, how to get count of hours for December for first or for second row at the screenshot?
I tried this (subMonths generated in the loop, so no worry about it):
$bookings = Booking::whereDate('departure_date', '>=', Carbon::now()->subMonths($i)->startOfMonth())
->orWhereDate('arrival_date', '<=', Carbon::now()->subMonths($i)->endOfMonth())->get();
and then:
foreach ($bookings as $book) {
echo Carbon::parse($book->departure_date.$book->departure_time)->diffInHours(Carbon::parse($book->arrival_date.$book->arrival_time));
}
But in this case I get count of hours for whole booking, how to get it only for December?
p.s. I need this for calculating the statistics (booking percentage).
You would likely need to ->addMonth() then go to the ->startOfMonth() then use diffInHours().
Carbon::parse($book->departure_date)
->addMonth()
->startOfMonth()
->diffInHours(Carbon::parse($book->arrival_date.$book->arrival_time));
I've omitted $book->departure_time otherwise the timestamp wouldn't be the first second of the first day of the month.

Laravel 5 search records 30min and older for today

I am trying to get all records that are 30min old and are today with a field called smsed value = to 0.
What i am trying to do is get all the records in my database with todays date and are older than 30min.
$data = DB::table('applicant')->whereRaw('AppDate < (NOW() - INTERVAL 30 MINUTE)')->where('smsed','=',0)->limit(5000)->get();
what the above does is get all records in the DB and not only for today.
This is because you only asking it for records that are over 30minutes old and not including anything to limit it to today.
You could use something like whereBetween:
$data = DB::table('applicant')
->whereBetween('AppDate', [Carbon\Carbon::now()->startOfDay(), Carbon\Carbon::now()->subMinute(30)])
->where('smsed', '=', 0)
->limit(5000)
->get();
Alternatively, if you just want to keep your sql functions you could do something like:
$data = DB::table('applicant')
->whereRaw('AppDate < (NOW() - INTERVAL 30 MINUTE)')
->whereRaw('DATE(AppDate) = CURDATE()')
->where('smsed','=',0)
->limit(5000)
->get();
Hope this helps!

Resources