Laravel Query using yyyy-mm--dd value on datetime column - mysql

I have written the following query using the laravel query builder. I am trying to get the count of fields in a column for a userID, activityID, and a date. It is the date field input that is causing the issue. I want to be able to return all the fields that have the same date as the date value I pass in. Below is my code.
$points = DB:: table("users_has_activities")
-> where("activitiesID", "=", $this->activityID)
-> where("usersID", "=", $userID)
-> where("time", "=", $date)
-> count();
$date will be a value like "2016-04-10", and the field in my table will have values like '2016-04-10 21:01:27'. I need to be able to get all the fields where the day of the date value matches the day of the datetime value in the table.

You can use the whereDay() method to get the DATE from DATETIME type:
$points = DB:: table("users_has_activities")
-> where("activitiesID", "=", $this->activityID)
-> where("usersID", "=", $userID)
-> whereDay("time", "=", $date)
-> count();

The best way to handle this is a whereBetween as it'll be able to use database indexes and doesn't need a calculation for each row in the DB:
$points = DB:: table("users_has_activities")
-> where("activitiesID", "=", $this->activityID)
-> where("usersID", "=", $userID)
-> whereBetween("time", '2016-04-12 00:00:00', '2016-04-12 23:59:59')
-> count();
Laravel's bundled Carbon can be handy for generating these dates. If your column is flagged as a date (see https://laravel.com/docs/5.2/eloquent-mutators#date-mutators) they'll be carbon objects already:
$start = $date->copy()->startOfDay();
$end = $date->copy()->endOfDay();

Related

Date between two values - Lavarel SQL

I have a structure table like this : Start_date End_date
Now with today's date, I should go and get all the data including from Start_Date and End_Date, what can I do?
I tried with
SELECT *
FROM text
WHERE Start_date BETWEEN '2021-10-10' AND '2021-10-08'
OR End_date BETWEEN '2021-10-08' AND '2021-10-10
but to no avail ...
The whereBetween method in Laravel will determine if an items value is between the given range.
$start = '2021-10-08';
$end = '2021-10-10';
Text::whereBetween('start_date', [$start, $end])
->whereBetween('end_date', [$start, $end])
->get();
if you just want to get data from start to end date you can use this eloquent Code
$start_date = "2020-10-20";
$end_date = "2021-10-20";
Text::where(function ($wh) use ($start_date, $end_date) {
$wh->whereBetween('Start_date', [$start_date, $end_date])->orwhereBetween('End_date', [$start_date, $end_date]);
})->get();
here is a raw query from the above eloquent code
select * from `users` where (`Start_date` between '2020-10-20' and '2021-10-20' or `End_date` between '2020-10-20' and '2021-10-20')
if you want to find data from start to end date including today's date you can you this eloquent Code
$start_date = "2020-10-20";
$end_date = "2021-10-20";
Text::where(function ($wh) use ($start_date, $end_date) {
$today_date = date('Y-m-d');
$wh->where(function ($or_where) use ($start_date, $end_date) {
$or_where->whereBetween('Start_date', [$start_date, $end_date])
->orwhereBetween('End_date', [$start_date, $end_date]);
})->orwhereRAW("('{$today_date}' between `Start_date` and `End_date`)");
})->get();
here is a raw query from the above eloquent code
select * from `text` where ((`Start_date` between '2020-10-20' and '2021-10-20' or `End_date` between '2020-10-20' and '2021-10-20') or ('2021-10-09' between `Start_date` and `End_date`))

Yii2 DB Expression in ActiveQuery::andFilterWhere()

I have the following code which filters an ActiveQuery
// Start date condition
if ($this->start_date) {
$query->andWhere('event_datetime >= :start_date', [
'start_date' => $this->start_date,
]);
}
// End date condition
if ($this->end_date) {
$query->andWhere('event_datetime < :end_date + INTERVAL 1 DAY', [
'end_date' => $this->end_date,
]);
}
where $this->start_date and $this->end_date are either null, '', or in the form Y-m-d, and event_datetime is an indexed DATETIME column
Provided that both date properties are true, this code produces the following SQL
WHERE event_datetime >= :start_date
AND event_datetime < :end_date + INTERVAL 1 DAY
I can rewrite the start date condition as
$query->andFilterWhere(['>=', 'event_datetime', $this->start_date);
Is it possible to rewrite the end date condition simlarly, perhaps using some kind of DB expression?
I'd rather keep the '+ INTERVAL 1 DAY' in SQL, if possible, and still be able to use an index on event_datetime
Apart from your date is null or empty '', what I am trying to understand is that why are you not using DateTime class along with DateInterval to set the $this->end_date to the final date after adding the interval and compare it with your column event_datetime rather than getting confused about it.
$endDate = $this->end_date;
if ($this->end_date !==null && $this->end_date!=='') {
$endDateObj = new \DateTime($this->end_date);
$endDateObj->add(new \DateInterval('P1D'));
$endDate = $endDateObj->format('Y-m-d');
}
$query->andFilterWhere(['<','event_datetime', $endDate]);
BUT, if you are still feeling sleepy head and dizzy and not feel like doing it in PHP for having personal reasons like increase in Blood Pressure, insomnia or your body start shivering thinking of PHP :P you can do it via \yii\db\Expression() in the following way which will produce the query like WHERE created_at < '2019-10-22' + INTERVAL 1 DAY, i have tested it but not sure how accurate it will be so test it before you go for it.
$query->andFilterWhere(
[
'<',
'event_datetime',
new \yii\db\Expression("'$this->end_date' + INTERVAL 1 DAY")
]
);
EDIT
You have to check manually the value for null and empty before you use any of the methods above and that is the only way you can do that. A little addition is needed to control the blank or null value which wont be controlled in the Expression automatically and will give incorrect results so change to the following
$expression = null;
$isValidDate = null !== $this->end_date && $this->end_date !== '';
//prepare the expression if the date is not null or empty
if ($isValidDate) {
$expression = new Expression(
":my_date + INTERVAL 1 DAY",
[
':my_date' => $this->end_date,
]
);
}
$query->andFilterWhere(
[
'>',
'end_date',
$expression,
]
);
A supplemental answer to #Muhammad's, and supported by #Michal's comment on my original question
The ActiveQuery::andFilterWhere() function ignores empty operands, so we can set up our expression or manipulated value, $endDate, to remain empty when the original value is empty
either using PHP's DateTime
$endDate = $this->end_date ?
(new DateTime($this->end_date . ' + 1 day'))->format('Y-m-d') :
null;
or using Yii's Expression
$endDate = $this->end_date ?
new Expression(':end_date + INTERVAL 1 DAY', ['end_date' => $this->end_date]) :
null;
Then ActiveQuery::andFilterWhere() can be used as follows
$query->andFilterWhere(['<','end_date', $endDate]);

max value from varchar date

I need to find max date from a table(mysql database). I am storing my date as varchar.
select max(completion_date) from table_name returns wrong value.
http://sqlfiddle.com/#!9/c88f6/3
Assuming the date time format you have in your fiddle (e.g. '12/19/2012 05:30 PM') then:
select max(STR_TO_DATE(completion_date, '%m/%d/%Y %l:%i %p')) from test;
http://sqlfiddle.com/#!9/c88f6/15
It's unclear if you want to factor the time into your rankings or just the date. This example accounts for time too, but you can remove that part of the formatter if desired.
I am not sure why you would want to keep it as varchar not date.
But this will work for varchar:
SELECT completion_date
FROM test
ORDER BY STR_TO_DATE(completion_date, '%m/%d/%Y') DESC LIMIT 1;
http://sqlfiddle.com/#!9/c88f6/10
<?php
// Store dates
$dates = array();
// Loop through and transfer the result set
foreach ($result as $row => $data) {
$dates[$row] = $data['date'];
}
// Sort the array
usort( $dates, "date_sort_function" );
// Max is last date in array.
foreach ($dates as $date) {
$max = $date;
}
?>
Well, something like that. It is a php script and all you have to provide is the sorting function which returns 0 if equal, 1 if older, and -1 if earlier.

Doctirne query builder, filtering by birthday (working with DateTime)?

I've a builder for selecting people with a phone number not null, a permission flag true (in the first builder call), and with a birthday template not null in this function. There is also a birthday field:
public function getAllForBirthdaySmsSend()
{
$qb = $this->getAllSuitableForSmsQueryBuilder();
$alias = $qb->getRootAlias();
$today = new \DateTime();
return $qb->andWhere(
$qb->expr()->andX(
$qb->expr()->isNotNull("$alias.sms_birthday_template"),
/* Filter if today is his birthday */
))
;
}
Now i should filter people by birthday, that is if birthday column formatted as 'm-d-' . date('Y') equals $today.
Anyone knows how to to this with query builder? I don't want to write pure SQL query but i prefer reusing the other query builder to be DRY.
You can use native sql and then map it in order to deal with real entities makeing use og ResultSetMapping. Of curse, the YEAR is ignored:
Mapping the query fields:
$rsm = new Doctrine\ORM\Query\ResultSetMapping;
$rsm->addEntityResult('models\User', 'u');
$rsm->addFieldResult('u', 'id', 'id');
$rsm->addFieldResult('u', 'username', 'username');
$rsm->addFieldResult('u', 'birthday', 'birthday');
Create a query using native date functions (each selected column now is mapped ):
$query = $this->doctrine->em->createNativeQuery('
SELECT id, username, birthday
FROM user
WHERE TIMESTAMPDIFF(YEAR, birthday, CURRENT_DATE)
> TIMESTAMPDIFF(YEAR, birthday, CURRENT_DATE - INTERVAL 1 DAY)', $rsm);
Get the users:
$users = $query->getResult();
Tip: Try to avoid casting column values when you want to do a query. It forces MySQL(if it is your case) to convert the column into a CHAR before performing the comparison and alter the performance.
Edit birthday column is datetime type. And the user model has the birtdate attibute mapped as \DateTime object

Codeigniter And MYSQL DateTime

I Have a query as follows:
$query = $this->db->get_where('Bookings', array('Status' => 0, 'Driver_ID' => null, 'Date'=> 'NOW()'));
The Date field is a datetime type, and I want to be garbing records where their date is the same as today, however the above, and everything else I have tired does not work.
Can anyone one show me how to correctly pull records that date it today, ignoring the time part of datetime.
Thanks for any help
UPDATE
I Have now converted the query to the following
$start = date('Y-m-d 00:00:00');
$end = date('Y-m-d 23:59:59');
$query = $this->db->get_where('Bookings', array('Status' => 0, 'Driver_ID' => null, 'Date' => 'BETWEEN '.$start.' AND '.$end));
However still no luck, just retuning no results!
I would try
$this->db->where('Status', 0);
$this->db->where('Driver_ID', null);
$this->db->where('DATE(Date)', date('Y-m-d'), FALSE);
$query = $this->db->get('Bookings');
$params = array('Status' => 0, 'Booking_Date'=> date('Y-m-d'));
$this->db->query('SELECT * FROM Bookings WHERE Status=? AND Driver_ID Is Null AND Date(Booking_Date) = ?',$params);
Think that will work
In your code, you are saying you want a DateTime field to be NOW(). The problem is that NOW() gives a DateTime value, that is, a date in the form "YYYY-MM-DD" followed by a time in the form "HH:MM:SS".
What your query is doing is saying "Give me records where the Date is today, at this exact second". What you want is "Give me records where the Date is today".
This is why using DateTime fields in a database is usually cumbersome. You will have to convert your Date field to be just the date, without the time, using the MySQL function DATE(), and instead of NOW() which returns a DateTime value, you will want to use CURDATE() which returns only the Date value. I am not experienced with CodeIgniter specifically, but try:
$query = $this->db->get_where('Bookings', array('Status' => 0, 'Driver_ID' => null, 'DATE(Date)'=> 'CURDATE()'));
(I don't know if you can apply MySQL functions to fields with $this->db->get_where).
MySql standard datetime format is date("Y-m-d H:i:s").
So you query will need to get everything for the current day, so a where clause someything like;
SELECT * FROM `Bookings` WHERE `Date` BETWEEN date("Y-m-d 00:00:00") AND date("Y-m-d 23:59:59")