I need to check if a time is after or before some time string. The database I have been given has times in multiple formats like 00:00:00 and 1970-01-01 07:00:00. Here is what I am trying to do:
data = {some_id:1, time_1:'1970-01-01 07:00:00', time_2:'1970-01-01 07:00:00'}
$results = $this->model->select(
'table.value as value'
)
->where('table.some_id', '=', $data['some_id'])
->where('table.time_1', '=>', $data['time_1'])
->orWhere('table.time_2', '<=', $data['time_2'])
->get();
But, this just returns every single value in the table. How do I compare dates like this when they are not technically dates?
Of course it will return all records.
Because logic of query is not correct.
For Your query sql will be like:
SELECT table.value AS value
FROM table
WHERE
table.some_id = 1
AND
table.time_1 <= '1970-01-01 07:00:00' OR table.time_2 => '1970-01-01 07:00:00'
But it should be:
SELECT table.value AS value
FROM table
WHERE
table.some_id = 1
AND
(table.time_1 <= '1970-01-01 07:00:00' OR table.time_2 => '1970-01-01 07:00:00')
To achieve this do nested where:
$results = $this->model->select(
'table.value as value'
)
->where('table.some_id', '=', $data['some_id'])
->where(function($q) use ($data) {
return $q->where('table.time_1', '=>', $data['time_1'])
->orWhere('table.time_2', '<=', $data['time_2']);
})
->get();
p.s. if it does not return proper response, I recommend to check dates that You request.
This would be the regular query
data = {some_id:1, time_1:'1970-01-01 07:00:00', time_2:'1970-01-01 07:00:00'}
$results = $this->model->select('table.value as value')
->where([
['table.some_id', '=', $data['some_id']],
[function($query) use($data){
query->where('table.time_1', '=>', $data['time_1'])
->orWhere('table.time_2', '<=', $data['time_2']);
}]
])->get();
If you need to transform the date there's a function called date() this transforms timestamps into date with the given format. Ex:
$date = 1497454883;
$date = date('Y-m-d H:i:s',$date);
date will be "2017-06-14 23:00:00"
If you have any questions let me know.
Related
I have a query for date range in Laravel that brings me to my head. Initially the query works without errors but I have detected that if the date range is between different years (12-2020 to 01-2021) it does not return any records. I'm a little tired of checking the code and I don't see the problem.
I put here the query that saves the data in an array and the check that I do later to apply the filter of the dates before returning the values.
public function getData($filters) {
$tasks = $this->getModel()
->whereIn('tasks.department_id', $filters['departmentIds'])
->join('departments', 'departments.id', '=', 'tasks.department_id')
->join('deliverables as dev', 'dev.id', '=', 'tasks.deliverable_id')
->leftJoin('deliverables as sub', 'sub.id', '=', 'tasks.subdeliverable_id')
->leftJoin('workers as st_workers', 'st_workers.id', '=', 'tasks.start_worker_id')
->leftJoin('workers as end_workers', 'end_workers.id', '=', 'tasks.end_worker_id')
->leftJoin('type_task_statuses', 'type_task_statuses.id', '=', 'tasks.status_id')
->leftJoin('incidences', 'incidences.task_id', '=', 'tasks.id')
->select('tasks.id', 'departments.name as department', 'tasks.start_worker_id', 'tasks.end_worker_id', 'st_workers.short_name as start_worker',
'end_workers.short_name as end_worker', 'tasks.plane', 'tasks.st', 'dev.name as deliverable', 'sub.name as subdeliverable',
'tasks.quantity', 'tasks.other_deliverable', 'tasks.start_prevision_date', 'tasks.end_prevision_date', 'tasks.start_date',
'tasks.end_date', 'tasks.prevision_hour', 'tasks.incurred_hour', 'type_task_statuses.display_name as status', 'type_task_statuses.color', 'tasks.advance', 'tasks.agreed',
'tasks.disagreed_date', 'tasks.supervised', DB::raw('COUNT(incidences.id) as count_incidences'))
->groupBy('tasks.id');
if (array_key_exists('fromDate', $filters) && $filters['fromDate']) {
$tasks->whereRaw('(DATE_FORMAT(tasks.end_date, "%m-%Y") >= "'.$filters['fromDate'].'" OR tasks.end_date is NULL)');
}
if (array_key_exists('toDate', $filters) && $filters['toDate']) {
$tasks->whereRaw('(DATE_FORMAT(tasks.end_date, "%m-%Y") <= "'.$filters['toDate'].'" OR tasks.end_date is NULL)');
}
return $tasks;
}
I would suggest to format your input to date range in your application rather than applying formatting on database side see my another answer for anit-patterns
Let say you have following input to match the date in database
$filters['fromDate'] ='12-2020';
$filters['toDate'] = '01-2021';
Which is equivalent to following date range in actual
From 2020-12-01 00:00:00 To 2021-01-31 23:59:59
So lets try to convert the filters input to this range format
/** 2020-12-01 00:00:00 */
$fromDate = \Carbon\Carbon::createFromFormat('d-m-Y', '01-'.$filters['fromDate'])->startOfMonth()->format('Y-m-d H:i:s');
/** 2021-01-31 23:59:59 */
$toDate = \Carbon\Carbon::createFromFormat('d-m-Y', '01-'.$filters['toDate'])->endOfMonth()->format('Y-m-d H:i:s');
Now you can easily apply these ranges in your query and on database side you wont need any kind of formatting
if (array_key_exists('fromDate', $filters) && $filters['fromDate']) {
$fromDate = \Carbon\Carbon::createFromFormat('d-m-Y', '01-' . $filters['fromDate'])->startOfMonth()->format('Y-m-d H:i:s');
$tasks->where(function ($query) use ($fromDate) {
$query->whereNull('tasks.end_date')
->orWhere('tasks.end_date', '>=', $fromDate);
});
}
if (array_key_exists('toDate', $filters) && $filters['toDate']) {
$toDate = \Carbon\Carbon::createFromFormat('d-m-Y', '01-' . $filters['toDate'])->endOfMonth()->format('Y-m-d H:i:s');
$tasks->where(function ($query) use ($toDate) {
$query->whereNull('tasks.end_date')
->orWhere('tasks.end_date', '<=', $toDate);
});
}
I need to select entries based on dates happening in the future and the
entries contain the date format:
12/30/17
I'm trying to format the date and compare to Carbon::now() timestamp, with no luck.
$now = \Carbon\Carbon::now();
$bookings = DB::table('booking')
->select('booking.*')
->where('booking.uid', '=', Auth::id())
->where(DB::raw("(DATE_FORMAT(booking.date,'%Y-%m-%d 00:00:00'))"), ">=", $now)
->get();
You'll need to use STR_TO_DATE to convert the string.
$bookings = DB::table('booking')
->select('booking.*')
->where('booking.uid', '=', Auth::id())
->where(DB::raw("(STR_TO_DATE(booking.date,'%m/%d/%y'))"), ">=", $now)
->get();
STR_TO_DATE will convert 12/30/17 to 2017-12-30
I don't think you really need to check date format. Also, you have some redundand stuff in the query. Just do this:
Booking::where('uid', auth()->id())->where('date', '>=', now())->get();
And if the date format is really different in some of the rows in the same column, you really need to fix this and instead of making some dirty fix for that.
$bookings = DB::table('booking')
->select('booking.*')
->where('booking.uid', '=', Auth::id())
->where(DB::raw("(DATE_FORMAT(booking.date,'%Y-%m-%d'))"), ">=", $now)
->get();
This is not showing the correct count. What is the correct syntax ?
$this->data['Tasks'] = \DB::table('tb_tasks')->where('Status', 'like', 'Open%')->whereDate('DeadLine', '>', 'CURDATE()')->count();
Use a Carbon instance:
$this->data['Tasks'] = \DB::table('tb_tasks')->where('Status', 'like', 'Open%')->whereDate('DeadLine', '>', Carbon::now())->count();
You can also use the now() helper
$this->data['Tasks'] = \DB::table('tb_tasks')->where('Status', 'like', 'Open%')->whereDate('DeadLine', '>', now())->count();
Use DB::raw:
->where('datefield', '>', \DB::raw('NOW()'))
We can also try this one. It works for me.
$date = "2020-04-10";
/*
Assumimng DB `login_date` datetime format is "Y-m-d H:i:s"
*/
$from_date = $date.' 00:00:01';
->where('login_date', '>=', $from_date);
By adding Where Clause in the query, we can find the result having
rows after the particular date.
Option-2:
$date = "2020-03-25"; // Format: date('Y-m-d);
$orders = DB::table('orders')
->select('*')
->whereDate('order_datetime', '<=', $date)
->get();
// Here, Table Field "order_datetime", type is "datetime"
// Assuming DB `order_datetime` stores value format like: "Y-m-d H:i:s"
you can make use of whereDate like below:
$query->whereDate('DeadLine', '>', Carbon::now())->count();
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 have a raw query which works fine.
$qry ="select date(created_at) as Date,count(id) as Value from performances where date_format(created_at,'%d-%m-%Y') >= '$start_date' and date_format(created_at,'%d-%m-%Y') <= '$to_date' group by Date order by Date desc ";
$stats = DB::select( DB::raw($qry) );
return json_encode($stats);
I would like to convert it in to Eloquent
My controller function is
public function postPerformanceDetails()
{
$start_date = Input::get('start_date');
$to_date = Input::get('to_date');
$start_date = date('Y-m-d',strtotime($start_date));
$to_date = date('Y-m-d',strtotime($to_date));
$stats = Performance::where('created_at', '>=', $start_date)
->where('created_at','<=',$to_date)
->groupBy('perf_date')
->orderBy('perf_date', 'DESC')
->remember(60)
->get([
DB::raw('Date(created_at) as perf_date'),
DB::raw('COUNT(id) as perf_count')
])
->toJSON();
return $stats
}
The raw query works fine but eloquent does not work according to the date input.
I input data in this format 09-03-2015
in database the format is 2015-03-09
If we give 2015-03-09 as start_date and to_date it returns empty string.
Is there any problem with formats?
How can i solve this issue?
The easiest way would be to convert the date in PHP to the database format.
$start_date = date('Y-m-d', strtotime($start_date));
This should lead to your database format: 2015-03-09.
I got the answer as #sleepless suggested.
This is the code.
public function postPerformanceDetails()
{
$event = Input::get('events');
$start_date = Input::get('start_date');
$to_date = Input::get('to_date');
$start_date = date('Y-m-d H:i:s',strtotime($start_date.'00:00:00'));
$to_date = date('Y-m-d H:i:s',strtotime($to_date.'23:59:59'));
$stats = Performance::where('created_at', '>=', $start_date)
->where('created_at','<=',$to_date)
->groupBy('perf_date')
->orderBy('perf_date', 'DESC')
->remember(60)
->get([
DB::raw('Date(created_at) as perf_date'),
DB::raw('COUNT(id) as perf_count')
])
->toJSON();
return $stats;
}