MySql - Finding "today" and "yesterday" while using CONVERT_TZ - mysql

I am struggling to get the correct definition of "today" and "yesterday" while using CONVERT_TZ() in MySql. My dates are stored in UTC, and I need to query the dates coming out in MST timezone, so something like this produces the correct start time of the day:
select DATE_FORMAT(convert_tz(utc_timestamp(),'+00:00','-07:00'), '%m/%d/%Y 00:00:00')
However, when I put it into a query, it doesn't seem to work.
This query correctly produces the last 24 hours, but not "today" (i.e. the time from midnight to now).
SELECT * FROM tablename
WHERE CONVERT_TZ(insertdate,'+00:00','-07:00') >= convert_tz(DATE_SUB(utc_timestamp(), INTERVAL 1 DAY),'+00:00','-07:00')
Then in similar form, this produces a query that is the 24 hours before 24 hours ago, but isn't "yesterday" (i.e. yesterday from 00:00:00 to 23:59:59 of yesterday's date in MST timezone).
select * from tablename
AND CONVERT_TZ(insertdate,'+00:00','-07:00') >= convert_tz(DATE_SUB(utc_timestamp(), INTERVAL 2 DAY),'+00:00','-07:00')
AND CONVERT_TZ(insertdate,'+00:00','-07:00') <= convert_tz(DATE_SUB(utc_timestamp(), INTERVAL 1 DAY),'+00:00','-07:00')

You need to format your date using date_format function and set the time as "00:00:00" query for today is
SELECT * FROM tablename
WHERE CONVERT_TZ(insertdate,'+00:00','-07:00') >= date_format(convert_tz(utc_timestamp(),'+00:00','-07:00'), '%y-%m-%d 00:00:00');
Yesterday:
SELECT * FROM tablename
WHERE CONVERT_TZ(insertdate,'+00:00','-07:00') between date_format(convert_tz(date_sub(utc_timestamp(), interval 1 day),'+00:00','-07:00'), '%y-%m-%d 00:00:00') and date_format(convert_tz(date_sub(utc_timestamp(), interval 1 day),'+00:00','-07:00'), '%y-%m-%d 23:59:59');

Related

How can I use DATEDIFF() to return rows where it has been more than 24 hours since it was added

I have table with column called date_added stored as datetime in MySQL.
I want to return rows where it has been 24 hours or more since it was added to the database.
I'm using the following query. However, it doesn't return what I want it to return.
SELECT * FROM campaign WHERE datediff(date_added,NOW())>=1
Here's what date_added in the Database looks like: 2017-08-15 00:48:31
You can do it this way
//This code is for SQL
SELECT *, DATEDIFF(HOUR,date_added,NOW()) AS Hours
FROM campaign WHERE DATEDIFF(HOUR,date_added,NOW()) >=24
As you can see i made the diff by hour
UPDATED
Try this one below.
SELECT * FROM campaign
WHERE HOUR(TIMEDIFF(DATE_FORMAT(date_added, "%Y-%m-%d %H:%i:%s"), DATE_FORMAT(NOW(), "%Y-%m-%d %H:%i:%s"))) >= 24
I used TimeDiff and used dateformat
and made it to hour.
You can also used this query
SELECT * FROM campaign WHERE TIMESTAMPDIFF(HOUR, date_added, NOW()) >= 24
Don't use any kind of "diff". Either of these will do match rows 'added' more than 24 hours ago.
WHERE date_added < NOW() - INTERVAL 1 DAY
WHERE date_added < NOW() - INTERVAL 24 HOUR
Since CURDATE() is midnight this morning, this will catch anything done anytime yesterday or today:
WHERE date_added < CURDATE() - INTERVAL 1 DAY

Select where unix timestamp falls on specified hour or day

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)

Select all MySQL records in the last day that are between a time range of 7am and midnight

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.

Find records with a time field in the last 24 hours

In my SQL query how do i find records in the last 24 hours?
I am using time() function for inserting into db.
I am using time-stamp the time is stored in this format.Eg 1332673046
select somefield from yourtable where timefield >= subtime(current_timestamp(), '1 00:00:00');
You can use BETWEEN
SELECT * FROM users
WHERE created_at BETWEEN '2012-03-31 00:00:00 UTC' AND '2012-03-31 23:59:59 UTC'
I am not certain if you are looking to check within the same calendar day, or as you say within the past 24 hours, so here's what I usually do for both cases:
a) For the same calendar day:
CONVERT(VARCHAR(8), myTable.myDate, 112) = CONVERT(VARCHAR(8), GETDATE(), 112)
b) For the date to be within the past 24 hours (inclusive)
DATEDIFF(hour, myTable.myDate, GETDATE()) <= 24
Simple DATE arithmetic would do,
SELECT *
FROM `table1`
WHERE `time_col` BETWEEN NOW() AND NOW()- INTERVAL 24 HOURS;
Given that you are storing dates as unix timestamps then you need UNIX_TIMESTAMP like this
SELECT
// fields you need
FROM `table`
WHERE
`date_field` BETWEEN UNIX_TIMESTAMP( DATE_SUB(NOW() INTERVAL 24 HOUR) ) AND UNIX_TIMESTAMP()
You might want to consider storing dates in MySQLs DATETIME format as it makes date calculations in MySQL much easier.

SELECT all records that are 30 days old

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.