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")
Related
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]);
I have a quiz application where played rounds are logged in UserPerformanceEntity. The corresponding MySQL table looks like:
UserPerformance
---------------
id (PK)
user
start_time
end_time
max_level
I want to display some statistics, like 'You performed better than x% of players'. To calculate the percent of players who performed worse than the current I want to execute the following MySQL query:
SELECT COUNT(DISTINCT `user`)
FROM `UserPerformance`
WHERE
(end_time IS NOT NULL
AND end_time NOT LIKE '0000-00-00 00:00:00')
AND `user` != :current_user
AND max_level < :current_level
ORDER BY max_level DESC
But I have no idea how to implement this with doctrine. How should my querybuilder look like?
try this
$query = $this->createQueryBuilder('u');
$query->select('COUNT(DISTINCT u.id) as usercount')
->where('u.end_time IS NOT NULL')
->andWhere('u.end_time NOT LIKE :end_time')
->andWhere('u.id != :current_userid')
->andWhere('u.max_level < :current_level')
->setParameter('end_time', '0000-00-00 00:00:00')
->setParameter('current_userid', $current_userid)
->setParameter('current_level', $current_level)
->setMaxResults(1);
$result = $query->getQuery()->getResult();
return $result[0]['usercount'] ;
The only change is, you need id from current user instead object
Additional information that a user can play many times, so user id is not unique, one user can have many records. This is my solution:
$em = $this->getDoctrine()->getManager();
$qb = $em->createQueryBuilder();
$result = $qb->select('COUNT(DISTINCT p.user) AS usercount')
->from('LoginetFBappVagoBundle:UserPerformanceEntity', 'p')
->where(
$qb->expr()->andX(
$qb->expr()->isNotNull('p.endTime'),
$qb->expr()->neq('p.endTime', ':endTime')))
->andWhere($qb->expr()->neq('p.user', ':userId'))
->andWhere($qb->expr()->lt('p.maxLevel', ':maxLevel'))
->setParameter('endTime', '0000-00-00 00:00:00')
->setParameter('userId', $userid)
->setParameter('maxLevel', $level)
->getQuery()
->getResult();
I started from #Alexander Keil's answer, but I used expressions, and I figured out that there is no need to group the (end_time IS NOT NULL AND end_time NOT LIKE '0000-00-00 00:00:00') part. However if I pass '0000-00-00 00:00:00' in the expression instead setting as a parameter, I get an error. And at last I have to count the distinct users the get the correct result.
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();
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.
I only want the dates starting from the current date. How do I ask this in CodeIgniter? "end_date" is a DATETIME (Y-m-d H:i:s).
This isn't working:
$this->db->select("DATE(end_date) as my_end_date", FALSE);
$this->db->where('my_end_date >', date());
$q = $this->db->get('tblTest');
You need to format the date in PHP so that it's in the format MySQL wants.
Try this:
$this->db->where('end_date >', date('Y-m-d H:i:s'));
You can also use MySQL's NOW() for this.
$this->db->where('end_date > NOW()', NULL, FALSE);
EDIT: If you want to use the alias my_end_date, you can use HAVING instead of WHERE.
$this->db->having('my_end_date > NOW()', NULL, FALSE);