I have data stored in a mySQL database and I want to retrieve the rows that have been inserted between now and the beginning of the current hour: not in the last hour, since the start of the hour. For example, at 9:16 I want the rows from 9:00 until now. My time is stored in datatime format. How can I do this?
The query below selects all rows that are between the current hour and current time. So if current time is 10:11 it will select all rows between 10:00 and 10:11 within current date.
SELECT *
FROM Test
WHERE mytime BETWEEN DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00')
AND DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s')
I Tested it and worked.
The first thing that comes to mind is:
select *
from t
where date(now() ) = date(t.timeval) and
hour(now() ) = hour(t.timeval)
I made the assumption that you don't have future records in the data. If so, then this comes to mind:
select *
from t
where date(now() ) = date(t.timeval) and
hour(now() ) = hour(t.timeval) and
timeval < now()
SELECT * FROM times WHERE t >= DATE_FORMAT(NOW(),'%Y-%m-%d %H:00:00');
Related
I'm trying to build a dynamic where for a MySQL query. The user can select how many hours or days ago they want data for. I want the data to fall on the particular hours or days ago.
Here is the code I'm using right now which does not work:
$condition['dates'] = 'Specific';
$condition['date_operand'] = 'Hour(s) ago';
$condition['date_value'] = '3';
if ($conditions['dates'] == 'Specific' && !empty($conditions['date_value'])) {
if ($conditions['date_operand'] == 'Hour(s) ago') {
$where[] = "date_format(from_unixtime(l.date_updated), '%Y-%m-%d %H') = date_format(now() - interval ".$conditions['date_value']." hour, '%Y-%m-%d %H')";
}
else if ($conditions['date_operand'] == 'Day(s) ago') {
$where[] = "date_format(from_unixtime(l.date_updated), '%Y-%m-%d') = date_format(now() - interval ".$conditions['date_value']." day, '%Y-%m-%d')";
}
}
It does not seem to be working whatsoever. The l.date_updated is a unix timestamp. You can see what I'm trying to achieve, it just isn't working.
UPDATE
Here is the MySQL where statement from the example which is not working:
SELECT * FROM mytable l
WHERE DATE_FORMAT(FROM_UNIXTIME(l.date_updated), '%Y-%m-%d %H') = DATE_FORMAT(NOW() - INTERVAL 3 HOUR, '%Y-%m-%d %H')
It does not cause an error, it simply isn't selecting what I want.
FINAL UPDATE
My query was actually fine. It appears my PHP code was connecting to a development database which hasn't been updated in years. That's why when I selected 3 days ago it returned zero rows.
So please, a little respect, for I am Dion, lord of the idiots.
It seems to me you want to choose rows where your date_updated value lies in a range of time. For example, I think you mean, if NOW() is 2017-04-03 17:55:22, you want all the records timestamped between 2017-04-03 14:00:00 and 2017-04-03 14:59:59.99999 inclusive.
Here's how you do that in a sargable way: a way that can use an index on your date_updated column.
This expression truncates NOW() to the top of the hour: 17:55 to 17:00:
DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00')
This backs up three hours.
DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00') - INTERVAL 3 HOUR
The beginning of your timestamp range is:
UNIX_TIMESTAMP(DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00') - INTERVAL 3 HOUR)
The end of your timestamp range, then, is
UNIX_TIMESTAMP(DATE_FORMAT(NOW(), '%Y-%m-%d %H:00:00') - INTERVAL 2 HOUR)
So, this WHERE clause does the trick.
WHERE l.date_updated >= UNIX_TIMESTAMP(DATE_FORMAT(NOW(),'%Y-%m-%d %H:00:00')-INTERVAL 3 HOUR)
AND l.date_updated) < UNIX_TIMESTAMP(DATE_FORMAT(NOW(),'%Y-%m-%d %H:00:00')-INTERVAL 2 HOUR)
Notice the <, not <=, at the end of the time range.
There's some time zone stuff happening here. Unix timestamps are (or should be) always recorded with respect to UTC. The UNIX_TIMESTAMP() function always converts from local time to UTC, and the NOW() function always works in local time, so this all should work properly. But you might investigate all this timestamp junk if you're still getting the wrong rows, or no rows.
Please notice that your time precision would be the same and your life would be easier if your column had the TIMESTAMP data type rather than the INT data type.
you can use TO_SECONDS:
https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_to-seconds
... where TO_SECONDS(l.date_updated) >= TO_SECONDS(NOW()-INTERVAL 3 HOUR)
I have a table called barcode_log, and these are all the datas from the table.
And now if I run this query
SELECT * FROM `barcode_log` WHERE barcode_log.assign_time BETWEEN DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY) AND CURRENT_DATE;
I get this result
But it should return all the rows as all the data is within this month only. And assign_time field is stored as datetime. Any idea what i am doing wrong??
You are ignoring the time part (hh:mm:ss).
If the end day is set to the end timestamp of the current date then you can get the data of current day's too.
BETWEEN is inclusive
SELECT
*
FROM
`barcode_log`
WHERE
barcode_log.assign_time BETWEEN DATE_SUB(
CURRENT_DATE,
INTERVAL 30 DAY
)
AND TIMESTAMP(CONCAT(CURDATE(),' ','23:59:59'));
While the accepted answer works, there is a simpler solution. Just take the date part of the datetime column:
SELECT
*
FROM
`barcode_log`
WHERE
DATE(barcode_log.assign_time)
BETWEEN DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY) AND CURRENT_DATE;
There is another way around: CAST() on barcode_log.assign_time field.
SELECT *
FROM `barcode_log`
WHERE CAST(barcode_log.assign_time AS DATE)
BETWEEN DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY) AND CURRENT_DATE;
This excludes time from comparison and works fine for your purpose.
I have this query
SELECT * FROM `timeclock_timecard`
WHERE `clock_in_datetime` > DATE_SUB(CURDATE(), INTERVAL 1 DAY)
which can get record in the last day but I need to limit to records created after 7AM
Any help please?
SELECT * FROM `timeclock_timecard`
WHERE `clock_in_datetime` > DATE_SUB(CURDATE(), INTERVAL 1 DAY)
and hour(`clock_in_datetime`) > 7;
Added one more filter condition to check for the hour.
Your query was almost correct, because CURDATE() only gives the date you can just subtract 17 hours to get the correct result. fiddle.
SELECT * FROM `timeclock_timecard`
WHERE `clock_in_datetime` >= DATE_SUB(CURDATE(), INTERVAL 17 HOUR)
To get the entries of the current day, we can add 7 hours (CURDATE() has time 0:00).
SELECT * FROM `timeclock_timecard`
WHERE `clock_in_datetime` >= DATE_ADD(CURDATE(), INTERVAL 7 HOUR)
To get only rows from yesterday, with a time value of 7AM or later, we can add 7 hours to the expression.
If we only up until midnight of today (just rows from yesterday), we can add another condition, the datetime is less than midnight today.
For example:
SELECT t.*
FROM `timeclock_timecard` t
WHERE t.`clock_in_datetime` >= DATE(NOW()) + INTERVAL -1 DAY + INTERVAL 7 HOUR
AND t.`clock_in_datetime` < DATE(NOW())
If you want to exclude the exact 7:00:00 AM value, change the >= to just >.
FOLLOWUP
Q: What I actually want is between about 5-6am TODAY and mindnight TODAY so anytime during today that I run the report for today I will get only timeclock data from users who clocked in/out today only and not include yesterdays data.
A: The predicates are going to be of the form
WHERE t.`clock_in_datetime` >= expr1
AND t.`clock_in_datetime` < expr2
You just need to find the expressions expr1 and expr2 that return the appropriate datetime values.
Just use a simple SELECT statement to test:
SELECT DATE(NOW()) + INTERVAL 5 HOUR AS `start`
, DATE(NOW()) + INTERVAL 1 DAY AS `end`
Q: I also modified my select to take in account my datetime is in UTC and my result needs to get todays records using local timezone.
SELECT * , CONVERT_TZ( clock_in_datetime , '+00:00', '-4:00' ) FROM `timeclock_timecard`
A: Personally, I would do the timezone conversion on the exprN values, not the column values. Having predicates on bare columns allows MySQL to make effective use of an index; wrapping the columns in expressions prevents MySQL from using an index.
If the MySQL system clock is UTC, and your datetime values stored in the table are in a different timezone, yes, use the MySQL CONVERT_TZ function.
Again, using a simple SELECT statement to develop and test the expressions:
SELECT CONVERT_TZ( DATE(NOW()) + INTERVAL 5 HOUR, '+0:00', to_tz) AS `start`
, CONVERT_TZ( DATE(NOW()) + INTERVAL 1 DAY , '+0:00', to_tz) AS `end`
Where to_tz is the timezone of the values in the table.
Once you get expressions start and end returning the values you need, then use those expressions in the predicates of the query of the timecard table.
I have a column in my table that is set as curret_timestamp, so the mysql database automatically puts the timestamp in when a record is created.
I need to get all records for the current day. At the moment I have my WHERE like this:
WHERE r.ts > DATE_SUB(NOW(), INTERVAL 1 DAY)
But this is giving me the last 24hrs. Which means that in the morning it still shows yesterday. So how can I say 'Give me all r.ts from 5am this morning?'
If you want all records with a timestamp from the current day later than 5am use
SELECT * FROM t
WHERE r.ts > CONCAT(CURDATE(), ' 05:00:00')
If you want all records with a timestamps since the last time it was 5am use
SELECT * FROM t
WHERE r.ts > CONCAT(IF(CURTIME() < '05:00:00', DATE_SUB(CURDATE(), INTERVAL 1 DAY), CURDATE()), ' 05:00:00')
The queries result only in different results from 00:00:00 - 04:59:59, so the first and easier alternative should be used, if there are no queries in that time.
You can try this-
select * from t
WHERE
DATE_FORMAT(t.ts,'%Y:%m:%d') = DATE_FORMAT(now(), '%Y:%m:%d') AND
DATE_FORMAT(t.ts,'%H:%i:%s') > STR_TO_DATE('05:00:00', '%H:%i:%s');
Explaination: The first condition check for current date and match it. And than it check for time it must be greater than morning 5 AM.
SQLFiddle
I need to SELECT all records that are 30 days old. I have the code below but it's not working. In updatestatus I have dates like 12/26/2011. I create a 30 day old date like
$onemonthago="01/01/2012";
$sth = $dbh->prepare(qq(
SELECT *
FROM people
WHERE STR_TO_DATE (updatestatus,'%m/%d/%y')
<= STR_TO_DATE ( "$onemonthago",'%m/%d/%Y')
) );
If the datatype of updatestatus is date:
SELECT *
FROM people
WHERE updatestatus <= '2012-01-01'
or:
SELECT *
FROM people
WHERE updatestatus <= CURRENT_DATE() - INTERVAL 1 MONTH
If the datatype is datetime or timestamp and you want to check the time part, too:
SELECT *
FROM people
WHERE updatestatus <= NOW() - INTERVAL 1 MONTH
You can put an exact datetime instead of the NOW() - INTERVAL 1 MONTH. The correct way depends on how you are storing the datetimes or timestamps (does the Perl code or MySQL creates them in the first place?).
You could also put - INTERVAL 30 DAY which yield slightly different results.
This is what I used. Very simple
$sth = $dbh->prepare(qq(SELECT * FROM people WHERE updatestatus + INTERVAL 30 DAY <= NOW() )) or die $DBI::errstr;
If the time column is in timestamp then use below query.(use from_unixtime function)
SELECT wd.* FROM `watchdog` as wd
WHERE from_unixtime(wd.timestamp) <= NOW() - INTERVAL 1 MONTH
You can try this way. In SQL, there is dateadd function and I think there should be similar function in MySQL.
select *
from Table
where str_to_date between dateadd(day,-30,getdate()) and getdate()
It retrieve records between current date and past 30 days. You need to adjust for time. If you don't count time, you need to remove timestamp.