Select from table where updated_at + 15minutes <= this_datetime - laravel

Hello I am seaching for a solution in Laravel 5 (eloquent) to select records form a table where updated_at + 15 minutes <= today (actual datetime).
I try this solution but it does not work :
$albums = Album::with(array('pictures' => function($q){
$q->whereDate('updated_at','<=', date("Y-m-d H:i:s", time() - (15*60)));
}))->get();
The result look always empty
dd($albums->pictures)

$currentTime = \Carbon\Carbon::now()->subMinutes(15);
above will give you equivalent to this mess 'date("Y-m-d H:i:s", time() - (15*60))'
I still don't understand why you need these 15 minute operation? But any way try this and let us know outcome.
$albums = Album::with(array('pictures' => function($q){
$currentTime = \Carbon\Carbon::now()->subMinutes(15);
$q->whereDate('updated_at','<=', $currentTime));
}))->get();

Related

Laravel date time condition not working properly

I have two columns in my offer table as follow, I want to fetch those offer's record which is currently active:
offer_start_date
offer_end_date
24-10-2022 10:57:00
24-10-2023 10:57:00
Below is my query date condition working fine but time is giving problems:
$now = Carbon::now();
$today = $now->toDateString();
$currentTime = $now->toTimeString();
$offers_data = Offer::whereRaw("offer_status=2 and offer_type=1 and is_special_offer=3")
->whereDate('offer_start_date','<=',$today)
->whereTime('offer_start_date','<=',$currentTime)
->whereDate('offer_end_date','>=',$today)
->whereTime('offer_end_date','>=',$currentTime)
->limit(10)
->get();
What would be the reason?
Using whereDate and whereTime together is likely not working the way you think it is.
Instead, try just using where() and Laravel will work it out for you.
$now = Carbon::now();
$offers_data = Offer::whereRaw("offer_status=2 and offer_type=1 and is_special_offer=3")
->where('offer_start_date', '<=', $now)
->where('offer_end_date', '>=', $now)
->limit(10)
->get();

How to get last 7 days records with 0 counts

I have an eloquent query that gets the total count records (created_at) of the last 7 days. But the problem is if one of these days have 0 records, this doesn't appear in the final data.
My query:
$data = Data::whereBetween('created_at', [Carbon::now()->subDays(6)->format('Y-m-d')." 00:00:00", Carbon::now()->format('Y-m-d')." 23:59:59"])
->groupBy('date')
->orderBy('date')
->get([
DB::raw('DATE(created_at) as date'),
DB::raw('count(*) as total')
])
->pluck('total', 'date')->toArray();
What I get:
[
"2020-04-14" => 1
"2020-04-16" => 1
"2020-04-18" => 1
"2020-04-19" => 1
]
What I expected:
[
"2020-04-14" => 1
"2020-04-15" => 0
"2020-04-16" => 1
"2020-04-17" => 0
"2020-04-18" => 1
"2020-04-19" => 1
"2020-04-20" => 0
]
Any suggestions?
SOLUTION:
-Based on Gary Houbre's proposal:
$results = Data::whereBetween('created_at', [Carbon::now()->subDays(6)->format('Y-m-d')." 00:00:00", Carbon::now()->format('Y-m-d')." 23:59:59"])
->groupBy('date')
->orderBy('date')
->get([
DB::raw('DATE_FORMAT(created_at, "%Y-%m-%d") as date'),
DB::raw('count(*) as total')
])
->keyBy('date')
->map(function ($item) {
$item->date = Carbon::parse($item->date);
return $item;
});
$period = new DatePeriod(Carbon::now()->subDays(6), CarbonInterval::day(), Carbon::now()->addDay());
$graph = array_map(function ($datePeriod) use ($results) {
$date = $datePeriod->format('Y-m-d');
return $results->has($date) ? $results->get($date)->total : 0;
}, iterator_to_array($period));
Looking directly Sql : How to include "zero" / "0" results in COUNT aggregate?
Into a same table : How to get the record if Count is zero in Laravel
You need to add an outer join into your request with Eloquent.
My idea is to create a for loop to check the days.
If there is no record on a date then print 0
Loop Iteration:
Catch the first Day (Suppose 14)
Catch the last Day
Then check in every iteration it is greater than one or many
Thus, I hope you will get normally.
We had a similar problem while trying to put back-end data into the chart. Since some of the days were missing it didn't look well. Our solution was;
Create a function like this;
public function generateDates(Date $startDate, Date $endDate, $format = 'Y/m/d'): Collection
{
$dates = collect();
$startDate = $startDate->copy();
for ($date = $startDate; $date->lte($endDate); $date->addDay()) {
$dates->put($date->format($format), 0);
}
return $dates;
}
In your case it's going to be (today and today - six days) and you will union returning collection with your query collection. What it does is; it create a date range from the keys and fill them with zero. When your query collection has some value other than zero - it is going to overwrite it.

Reproduce in eloquent

I am not able to reproduce this query in eloquent.
How could I have made a query without eloquent?
select * from points where operator = 2 and (month(date) = '1' and day(date) >= 25 or month(date) = '2' and day(date) <= 24)
You may use DB facade for this purpose..
$query = "select * from points where operator = :operator and (month(date) = :monthDate and day(date) >= :dayDate or month(date) = :monthDate2 and day(date) <= :dayDate2)"
$points = DB::select($query,[
"operator" => 2,
"monthDate" => 1,
"dayDate" => 25,
"monthDate2" => 2,
"dayDate2" => 24
])
Considering you have Point model for points table, below eloquent query should work :
<?php
$points = Point::where('operator', 2)->where(function($q){
return $q->whereMonth('date', '=', 1)->whereDay('date', '>=', 25);
})->orWhere(function($q){
return $q->whereMonth('date', '=', 2)->whereDay('date', '<=', 24);
})->get();

Refactor Laravel Query

I have a query that I have built, and I am trying to understand how I can achieve the same thing but in one single query. I am fairly new to Laravel and learning. Anyway someone could help me understand how I can achieve what I am after?
$activePlayerRoster = array();
$pickupGames = DB::table('pickup_games')
->where('pickupDate', '>=', Carbon::now()->subDays(30)->format('m/d/Y'))
->orderBy('pickupDate', 'ASC')
->get();
foreach ($pickupGames as $games) {
foreach(DB::table('pickup_results')
->where('pickupRecordLocatorID', $games->recordLocatorID)
->get() as $activePlayers) {
$activePlayerRoster[] = $activePlayers->playerID;
$unique = array_unique($activePlayerRoster);
}
}
$activePlayerList = array();
foreach($unique as $playerID) {
$playerinfo = DB::table('players')
->select('player_name')
->where('player_id', $playerID)
->first();
$activePlayerList[] = $playerinfo;
}
return $activePlayerList;
pickup_games
checkSumID
pickupDate
startTime
endTime
gameDuration
winningTeam
recordLocatorID
pickupID
1546329808471
01/01/2019
08:03 am
08:53 am
50 Minute
2
f47ac0fc775cb5793-0a8a0-ad4789d4
216
pickup_results
id
checkSumID
playerID
team
gameResult
pickOrder
pickupRecordLocatorID
1
1535074728532
425336395712954388
1
Loss
0
be3532dbb7fee8bde-2213c-5c5ce710
First, you should try to write SQL query, and then convert it to Laravel's database code.
If performance is not critical for you, then it could be done in one query like this:
SELECT DISTINCT players.player_name FROM pickup_results
LEFT JOIN players ON players.player_id = pickup_results.playerID
WHERE EXISTS (
SELECT 1 FROM pickup_games
WHERE pickupDate >= DATE_FORMAT(SUBDATE(NOW(), INTERVAL 30 DAY), '%m/%d/%Y')
AND pickup_results.pickupRecordLocatorID = recordLocatorID
)
Here I'm assuming you know what you're doing with this dates comparison, because it looks weird to me.
Now, let's convert it to Laravel's code:
DB::table('pickup_results')
->select('players.player_name')->distinct()
->leftJoin('players', 'players.player_id', '=', 'pickup_results.playerID')
->whereExists(function ($query) {
$query->select(DB::raw(1))
->from('pickup_games')
->where('pickupDate', '>=', Carbon::now()->subDays(30)->format('m/d/Y'))
->whereRaw('pickup_results.pickupRecordLocatorID = recordLocatorID');
})
->get();
Basically, I would reduce the query to its SQL variant to get directly at its core.
The essence of the query is
select `x` FROM foo WHERE id IN (
select distinct bar.id from bar join baz on bar.id = baz.id);
This can be interpreted in Eloquent as:
$thirtyDaysAgo = Carbon::now()->subDays(30)->format('m/d/Y');
$playerIds = DB::table('pickup_games')
->select('pickup_games.player_id')
->join(
'pickup_results',
'pickup_results.pickupRecordLocatorID',
'pickup_games.recordLocatorID')
->where('pickupDate', '>=', $thirtyDaysAgo)
->orderBy('pickupDate', 'ASC')
->distinct('pickup_games.player_id');
$activePlayers = DB::table('players')
->select('player_name')
->whereIn('player_id', $playerIds);
//>>>$activePlayers->toSql();
//select "player_name" from "players" where "player_id" in (
// select distinct * from "pickup_games"
// inner join "pickup_results"
// on "pickup_results"."pickupRecordLocatorID" = "pickup_games"."recordLocatorID"
// where "pickupDate" >= ? order by "pickupDate" asc
//)
From the resulting query, it may be better to refactor the join as relationship between the Eloquent model for pickup_games and pickup_results. This will help to further simplify $playerIds.

Laravel carbon retrieve record even when it shouldn't

I am searching by start and end date or with a weekday, which kind of works fine however if weekday is equal to 'WE' and today's weekday is equal to 'WE' it still brings back results even when $today date is < than endate.
public function show($id)
{
$weekMap = [
0 => 'SU',
1 => 'MO',
2 => 'TU',
3 => 'WE',
4 => 'TH',
5 => 'FR',
6 => 'SA',
];
$todayWeek = Carbon::now()->dayOfWeek;
$today= Carbon::now();
$weekday = $weekMap[$todayWeek];
$event = Event::with('businesses')
->where('startdate', '<', $today->format('Y-m-d'))
->where('endate', '>', $today->format('Y-m-d'))
->orWhere('weekday', '=', $weekday)
->get();
dd($event);
return view('events.showEvent', compact('event'));
}
If I change orWhere to where, results are all good, however user not always enters a weekday so it can be empty. I want it to work like this:
output everything where startdate < today and where endate > today and if weekday is not empty, output everything where startdate < today, endate > today and weekday = $weekday. I hope that makes sense.
//edit
sample data:
data
So what I want is really search by frequency so it would look like this:
if frequency = daily
compare start and end with today's date.
if frequency = weekly
compare start and end with today's date and weekday.
bring back all results for frequency = daily+weekly
you can use if condition in query like this:
$query = Event::with('businesses')
->where('startdate', '<', $today->format('Y-m-d'))
->where('endate', '>', $today->format('Y-m-d'));
if ($weekday != '') {
$query->where('weekday', $weekday);
}
$event = $query->get();
also
condition if ($weekday != '') check $weekday isset or not you can use
if ( ! is_null($weekday )) instead

Resources