I run a website that stores images and users get a hotlink.
I want to be able to query records made in the last 7 days in the table containing the uploaded image data, extract the created_at column only, and compile the data into an array, similar to making an archive list for a blog.
I would like for the results to be presented like:
[
'Sunday' => 5,
'Monday' => 45,
'Tuesday' => 452,
...
]
Where each number represents the number of records created on each day. As long as I can output an array like that, I can handle the Javascript side easily.
Anybody have any suggestions?
EDIT
This is the code I've tried so far:
<?php
class Admin
{
public function getCreatedAtAttribute($value)
{
$this->attributes['created_at'] = Carbon::createFromFormat('Y-m-d H:i:s', $value);
}
public static function uploadsGraph()
{
$date = \Carbon\Carbon::now();
$uploads = Upload::select('created_at')->where('created_at', '>=', \Carbon\Carbon::now()->subWeek())->get();
foreach($uploads as $date)
{
echo $date->created_at . '<br>';
}
}
}
EDIT 2
Here's another version I tried, but that didn't work out well.
class Admin
{
public static function uploadsGraph()
{
$date = \Carbon\Carbon::now();
$uploadsByDay = DB::table('uploads')
->select(DB::raw('
YEAR(created_at) year,
MONTH(created_at) month,
MONTHNAME(created_at) month_name
'))
->groupBy('year')
->groupBy('month')
->orderBy('year', 'desc')
->orderBy('month', 'desc')
->get();
dd($uploadsByDay);
}
}
I'm assuming that the number next to each day of the week represents the number of records made on that day, with the entire dataset you want to query ranging only over the last 7 days.
The idea here is to select the count of items that were created on the same day (ignoring completely the timestamp portion of the created_at column), so we can use DB::raw inside of a select() call to aggregate all of the entries that were created on a specific day and then restrict that dataset to only those created in the last week. Something like this ought to work:
$data = Upload::select([
// This aggregates the data and makes available a 'count' attribute
DB::raw('count(id) as `count`'),
// This throws away the timestamp portion of the date
DB::raw('DATE(created_at) as day')
// Group these records according to that day
])->groupBy('day')
// And restrict these results to only those created in the last week
->where('created_at', '>=', Carbon\Carbon::now()->subWeeks(1))
->get()
;
$output = [];
foreach($data as $entry) {
$output[$entry->day] = $entry->count;
}
print_r($output);
Also note that I assumed this to be a 'rolling' week, where if today happens to be a Thursday, then the first date in the dataset will be the previous Thursday. It will not start on the most recent Sunday, if that is what you need. If it is, you can change the -where() condition to something like this:
...
->where('created_at', '>=', Carbon\Carbon::parse('last sunday'))
...
DB::table("clicks")
->select("id" ,DB::raw("(COUNT(*)) as total_click"))
->orderBy('created_at')
->groupBy(DB::raw("MONTH(created_at)"))
->get();
Related
I am trying to get the sum of a field 'time_spent' for the current month, so when it's the next month it will start over again. I currently have in my model:
public function transactions()
{
return Transaction::groupBy('created_at')
->selectRaw('sum(time_spent) as sum')
->pluck('sum');
}
Then in my blade view I am calling using:
$info->transactions()->sum()
This does return the sum of time_spent from the DB, but it doesn't care about the created_at, I am assuming its not using it, My column for created_at is timestamp()
You need to use the methods whereMonth and whereYear to filter the transactions by the current month and year. After that, you can use the database's sum method to sum all time_spent.
Your method should look like this:
public function transactions($year, $month)
{
return Transaction::whereYear('created_at', $year)
->whereMonth('created_at', $month)
->sum('time_spent');
}
This will run a query similar to this (it depends on which database you're using):
SELECT SUM(transactions.time_spent) FROM transactions WHERE YEAR(transactions.created_at) = 2018 AND MONTH(transactions.created_at) = 11;
To get the current month, you should call the method like this:
$month = date('m');
$year = date('Y');
$transactions = $info->transactions($month, $year);
created_at is a timestamp from year to the second (YYYY-MM-DD HH:mm:ss).
If you are trying to sum by some month, you need to identify the year and month to do this.
So, use this instead:
public function transactions($year, $month)
{
return Transaction::selectRaw('sum(time_spent) as sum')
->where('YEAR(created_at)', '=', $year)
->where('MONTH(created_at)', '=', $month)
->pluck('sum');
}
$year = 2018; //change in application
$month = 11; //change in application
$info->transactions($year, $month)->sum();
I need to implement showing of some events on an existing project. I can not change database structure.
In my controller I get passed (from ajax request) a timestamp and I need to show previous 8 events. So if timestamp is (converted) 2017-12-12 00:00:00 I need to show 8 events before 2017-12-12, ordered by their time DESC.
This is how my table is set up:
-calendarrepeat
-dayofweek // int 1-7; 1 = monday, 7 = sunday
-event_date_begin // date "2016-05-01" - indicates from which day the event recurrs every week (dayofweek)
-event_date_end // date "2017-05-02" - indicates until which day the event recurrs every week (dayofweek)
-event_hour_begin // time "11:00:00"
-event_hour_end // time "12:00:00"
I can do whatever I want with the timestamp. I use Carbon so it's not a problem to get week of the year, day of the year or whatever else I would need.
For reference $fullTs is the timestamp I get passed into the controller. The join part works fine.
The part I need help with is: /* THIS PART has to be rewritten (it's COMPLETELY wrong at the moment) ! */
I need to generate timestmap from year (passed as argument), weekOfYear (passed as argument), day of week (from database column) and time (database column). I would need something like this instead (pseudoSQL):
->where(\DB::raw('THISTHINGY_TO_DATE($fullTs->year $fullTs->weekOfYear calendarrepeat.dayofweek calendarrepeat.event_hour_begin, "%Y %week-of-year %day-of-week %H:%i:%s), '<', $fullTs)))
This is the full query I'm currently running (the first part of UNION, the second one works as intended):
$eventsRepeat = CalendarRepeat::join('calendarrepeat_translations', function ($j) use ($locale) {
$j->on('calendarrepeat.id', '=', 'calendarrepeat_translations.calendarrepeat_id')
->where('calendarrepeat_translations.locale', '=', $locale);
})
->orderBy('calendarrepeat.event_date_begin', $orderBy)
/* THIS PART has to be rewritten (it's COMPLETELY wrong at the moment) ! */
/* the STR_TO_DATE(..) part has to get date from a) week passed in $fullTs b) dayoftheweek written in calendarrepeat.dayoftheweek c) time written in calendarrepeat.event_hour_begin */
->where(\DB::raw("STR_TO_DATE(CONCAT(calendarrepeat.event_date_begin, ' ', calendarrepeat.event_hour_begin), '%Y-%m-%d %H:%i:%s')"), '<', $fullTs)
->where('event_date_begin', '>', $fullTs)
->where('event_date_end', '<', $fullTs)
->limit(8)
->select([
'calendarrepeat.event_date_begin as date', 'calendarrepeat.event_hour_begin as start',
'calendarrepeat.event_hour_end as end', 'calendarrepeat_translations.title as title', \DB::raw("CONCAT(calendarrepeat.event_date_begin, ' ', calendarrepeat.event_hour_begin) as date_whole") // This is also wrong
]);
Is that possible? How? Is there a better way to go about doing this?
Another thing to be careful about is that in our DB 1 = monday, 7 = sunday, which from my understanding isn't a common way to enumerate week days.
Thanks in advance.
Try this and check the result you have got:
$eventsRepeat = CalendarRepeat::join('calendarrepeat_translations', function ($j) use ($locale) {
$j->on('calendarrepeat.id', '=', 'calendarrepeat_translations.calendarrepeat_id')
->where('calendarrepeat_translations.locale', '=', $locale);
})->select([
'calendarrepeat.id',
'calendarrepeat_translations.calendarrepeat_id',
'calendarrepeat_translations.locale','calendarrepeat.event_date_begin as date',
'calendarrepeat.event_hour_begin as start',
'calendarrepeat.event_hour_end as end',
'calendarrepeat_translations.title as title',
\DB::raw("CONCAT(calendarrepeat.event_date_begin, ' ', calendarrepeat.event_hour_begin) as date_whole")
])->where(\DB::raw("STR_TO_DATE(CONCAT(date, ' ', start), '%Y-%m-%d %H:%i:%s')"), '<', $fullTs)
->where('date', '>', $fullTs)
->where('end', '<', $fullTs)
->orderBy('date', $orderBy)
->limit(8);
I'm trying to write a certain query but I'm failing with it and I'm looking for some help
Here's what I want to do
SELECT all items WHERE created_at is from before this month (July, June,...), and also select the first 3 which are created during this month
this is what I currently have. I've tried numerous times, but I can't figure out the right "WHERE" case
$offertes = DB::table('offertes')
->select('*')
->where('receiver_id', $user_id)
...
->orderby('seen')
->orderby('created_at','desc')
->get();
Something like this should work:
$time = new Carbon\Carbon('first day of this month'); // Get first day of the month.
$time->setTime(0, 0, 0); // Set time to 00:00:00.
....
->where('created_at', '<', $time)
->where(function($q) {
$q->where('created_at', '>', $time)
->orderby('created_at','asc')
->take(3)
})
->get;
I want to find out if a product is trending on my website (trending up or down) based on the period that is passed in. I.e. If week is passed in, it compares the current week up to the day to the previous week up to the same day.
e.g. If today is Wednesday, and the mode is week, it will compare this week up to today, with last week up to last Wednesday.
I have so far:
public function getTrendAttribute($period)
{
$last_period = $this->ratings()->where(DB::raw(), )->avg('rating');
$this_period = $this->ratings()->where(DB::raw(), )->avg('rating');
}
Which I don't think is the correct start :(.
How can I achieve this (I have the Carbon library in my app)?
What about this? I am not sure if it is very efficient but it seems to be giving me some numbers that make sense:
public function getTrendAttribute($period)
{
$tz = 'Europe/London';
$this_week_start = Carbon::now($tz)->startOfWeek();
$now = Carbon::now($tz);
$last_week_start = Carbon::now($tz)->subWeek(1)->startOfWeek();
$now_last_week = Carbon::now($tz)->subWeek(1);
$last_period = $this->ratings()->where('created_at', '>=', $last_week_start)->where('created_at', '<=', $now_last_week)->avg('rating');
$this_period = $this->ratings()->where('created_at', '>=', $this_week_start)->where('created_at', '<=', $now)->avg('rating');
return $last_period > $this_period ? -1 : $last_period < $this_period ? 1 : 0;
}
Try this. Note that it is specific to the week grouping, and you would have to modify that query for grouping by month, or day, or anything else like that. But you should be able to use MySQL date functions to accomplish this.
$last_period = $this->ratings()->where(DB::raw('week(created_at)'), DB::raw('week(now()) - 1'))->where(DB::raw('dayofweek(created_at)'), '<=', DB::raw('dayofweek(now())'))->avg('rating');
$this_period = $this->ratings()->where(DB::raw('week(created_at)'), DB::raw('week(now())')->avg('rating');
I want to get count of one week old created records as of yesterday in laravel using created_at time stamp, I have:
//week date range upto current day
$name_current_day = date("l");
$name_current_week = date("Y-m-d",strtotime('monday this week')).'to'.date("Y-m-d",strtotime("$name_current_day this week"));
//query to get count
foreach($name_list as $name){
//created in week
$data[$network->name.'_week'] = Info::select( DB::raw('DATE(`created_at`) as `date`'),DB::raw('COUNT(*) as `count`'))
->where('created_at', '>', $name_current_week)
->where('name',$name->f_name)
->groupBy('date')
->orderBy('date', 'DESC')
->lists('count', 'date');
}
When I run this query, I am not getting accurate results, Is this the cirrect way to get last 7 days records in Laravel.
You need to compare date() as well, and it's easier to use Carbon, though you don't need that. It's up to you.
EDIT: your question is a bit unclear, but it seems that you don't want week-old, but only current week's results.
Anyway, this will work for you:
// week old results:
// $fromDate = Carbon\Carbon::now()->subDays(8)->format('Y-m-d');
// $tillDate = Carbon\Carbon::now()->subDay()->format('Y-m-d');
// this week results
$fromDate = Carbon\Carbon::now()->subDay()->startOfWeek()->toDateString(); // or ->format(..)
$tillDate = Carbon\Carbon::now()->subDay()->toDateString();
Info::selectRaw('date(created_at) as date, COUNT(*) as count'))
->whereBetween( DB::raw('date(created_at)'), [$fromDate, $tillDate] )
->where('name',$name->f_name)
->groupBy('date')
->orderBy('date', 'DESC')
->lists('count', 'date');
You can use Carbon for this, which makes working with dates easier in Laravel. It's included with the framework. You can then do this:
$yesterday = Carbon::now()->subDays(1);
$one_week_ago = Carbon::now()->subWeeks(1);
foreach($name_list as $name){
//created in week
$data[$network->name.'_week'] = Info::select( DB::raw('DATE(`created_at`) as `date`'),DB::raw('COUNT(*) as `count`'))
->where('created_at', '>=', $one_week_ago)
->where('created_at', '<=', $yesterday)
->where('name',$name->f_name)
->groupBy('date')
->orderBy('date', 'DESC')
->lists('count', 'date');
}