Suppose I have a table containing a month's transaction data with transaction_time stored in a DATETIME field.
I want to get all the transactions that occurred between 12:00:00 and 13:00:00, irrespective of the day. WHERE transaction_time BETWEEN x AND y would have to be date-specific, but I need that same time period of all dates.
How can I filter for such a range in a MySQL query?
You can filter on the result of applying MySQL's HOUR() function to your DATETIME value:
WHERE HOUR(transaction_time) = 12
If you need to filter across more exact time ranges, you could convert the times to seconds as follows:
WHERE TIME_TO_SEC(TIME(transaction_time)) BETWEEN TIME_TO_SEC('12:00:00')
AND TIME_TO_SEC('13:00:00')
You can use:
select * from transactions
where convert(time, transaction_time) between '12:00:00' and '13:00:00'
for MSSQL and:
select * from transactions
where extract(hour_second from transaction_time) between 120000 and 130000
for MySql.
You have two time constraints. The first is to restrict the dates to a particular month. Assume we get the first day of the month as a date parameter:
where transaction_time >= :searchMonth
and transaction_time < Date_Add( :searchMonth, interval 1 month )
Now we're only looking at rows from that month. Now limit it to the hour specified. Assume we get the hour as an integer parameter:
and extract( hour from transaction_time ) between :hr and (:hr + 1)
Now that final part is based on your own code. Let me say that when the requirements read "during a particular hour of the day" and the request reads "during the noon hour" then I am wont to write it like this:
and extract( hour from transaction_time ) >= :hr
and extract( hour from transaction_time ) < (:hr + 1)
because hour 13 (1PM) is the first click of the next hour. So if there is a transaction time at exactly 13:00:00 and you use between, then it will show up when looking at the noon hour and also when looking at the 1PM hour. That is NOT generally a desired result. You may want to verify that with your analyst.
So the complete filter, the way I would write it, is this:
where transaction_time >= :searchMonth
and transaction_time < Date_Add( :searchMonth, interval 1 month )
and extract( hour from transaction_time ) >= :hr
and extract( hour from transaction_time ) < (:hr + 1)
Related
I want to know is it possible in mysql query.. when I say give me date when it is 9am.. the return answer is depends upon current time when it is 8am it give me today's date. when it is 10pm it gives me tomorrow date. how it is possible in mysql query.
You can use SUBSTRING_INDEX(CURTIME(), ':', 1) to get the hours of current time.
As I understood you want to get tomorrow date, if it is 10pm or later
Example given:
SELECT
CASE
WHEN SUBSTRING_INDEX(CURTIME(), ':', 1) >= 22
THEN DATE_ADD(CURDATE(), INTERVAL 1 DAY)
ELSE CURDATE()
END
Source: http://www-db.deis.unibo.it/courses/TW/DOCS/w3schools/sql/sql_dates.asp.html
You can get the hour value from a given datetime expression, using HOUR function. CURDATE() function is used to return the current date. You can add/subtract 'integers' to it get the date corresponding to current date +/- 'integer days' . Assuming that the time >= 10 pm returns next day:
SELECT IF(HOUR(`datetime_field`) > 22, CURDATE(), CURDATE() + 1);
You could just add 2 hours
SELECT DATE(DATE_ADD(NOW(), INTERVAL 2 HOUR));
This will then return tomorrow’s date for anytime after 10pm.
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.
Why this query is not working
SELECT * FROM history WHERE DATE(date) < CURDATE() + 30
I am trying to get the data from 30 days but my query is not working.Why
What does +30 mean? Days? Years? Months? Hours? You need to use (the proper syntax) a format MySQL understands:
SELECT * FROM history WHERE DATE(date) < CURDATE() + INTERVAL 30 DAY
To get the data from today on to 30 days after current day, you've got to set an upper and an lower limit, so use:
SELECT * FROM history WHERE
date >= CURDATE()
AND
date < CURDATE() + INTERVAL 31 DAY
Please note that by not using a function on your date column you won't prohibit MySQL to use an index on this column.
The lower limit should be obvious, the upper limit means that you've got the complete day that's 30 days later than today. If you use + INTERVAL 30 DAY instead this last day is excluded from the result.
Because you're not using the right construct, try:
SELECT * FROM history WHERE DATE_ADD(date, INTERVAL 30 DAY);
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.