Mysql Datediff query - mysql

I need to get the result from the table, which the date should be difference of 5 from the current date.
ie., specific_date column is present in my table. The format of the date is YYYY-MM-DD.
I need the query something like,
SELECT * FROM `table_name` WHERE DATEDIFF(NOW(), specific_date) < 5

It looks like you are trying to do this:
WHERE specific_date < (NOW() + 5 days)
First of all, think carefully about the boundary cases. These boundary cases can bite your ankles in SQL. Do you actually want
WHERE specific_date <= (NOW() + 5 days)
Do your specific_date columns timestamps contain only days (that is dates with times equal to midnight) or do they contain dates and times? If you're going to get the results you want, you need to be careful about those details.
At any rate, try this:
WHERE specific_date <= DATE_ADD(NOW(), INTERVAL 5 DAY)
This is a good way to do such a lookup. The column value stands alone on one side of the inequality predicate (the <=) so mySQL can do an index range scan if you have an index on the column.
Date arithmetic in MySQL is quite flexible. You can do
NOW() + INTERVAL 10 SECOND
NOW() - INTERVAL 2 MINUTE
NOW() + INTERVAL 4 HOUR
CURDATE() - INTERVAL 1 WEEK /* midnight one week ago */
LAST_DAY(NOW()) + INTERVAL 1 DAY - INTERVAL 1 MONTH /*first day of present month*/
NOW() - INTERVAL 1 QUARTER
CURDATE() - INTERVAL 5 YEAR
and so forth.

Have a look at the BETWEEN operator.
expr BETWEEN min AND max
Another way is to use the DATE_SUB operator
WHERE date_column > DATE_SUB(NOW(), INTERVAL 5 DAY)

Related

Create a dynamic time range in sql

Is there a way to create a dynamic way to make a sql query that queries the data between the first day and the last day of every current month? I have a field called created and and I want to get the data where created is between the first day and the last day of the month.
Something like this will do it:
WHERE created BETWEEN DATE_FORMAT(Now(), '%Y-%M-01 00:00:00') AND DATE_FORMAT(DATE_ADD(DATE_ADD(Now(),INTERVAL 1 MONTH), INTERVAL -12 HOUR), '%Y-%M-%d 23:59:59')
It’s not pretty, but it gets the job done.
Is there a way to create a dynamic way to make a sql query that queries the data between the first day and the last day of every current month?
A simple method uses just date functions:
where created_at >= curdate() + interval (1 - day(curdate()) day and
created_at < (curdate() + interval (1 - day(curdate()) day) + interval 1 month
In addition to only using date arithmetic, this doesn't have an error of missing the last second of the month.

select data on specific date

I want to retrieve records from db according to date format YYYY,MM,dd given by me but the column type is YYYY,MM,dd hh:mm:ss.
tried to use Date format function
SELECT *
FROM tabl.error_logs
where created_at = DATE_FORMAT(NOW(),'%Y-%m-%d'- INTERVAL 3 DAY);
I expect the created date will be 2019-06-08, but the result is empty
What is the actual datatype of created_at column?
This answer is going to ignore that funkiness with the format with commas, and assume that it's not character type data, and that it's DATETIME or TIMESTAMP.
Normative pattern for predicates on DATETIME and TIMESTAMP columns is a range comparison.
For example, to get all datetimecol values on June 10th, then something like this:
WHERE t.datetimecol >= '2019-06-10 00:00:00'
AND t.datetimecol < '2019-06-11 00:00:00'
Typically, I would just pass that one date value, and let MySQL figure out the next day. If we omit the time portion, MySQL will assume 00:00:00
WHERE t.datetimecol >= '2019-06-10' + INTERVAL 0 DAY
AND t.datetimecol < '2019-06-10' + INTERVAL 1 DAY
For performance, to allow MySQL to make effective use of a range scan operation on a suitable index, we want to avoid wrapping the column reference in a function. That is, specifying DATE(t.datetimecol) in a condition in the WHERE clause is going to force MySQL to evaluate the DATE() function on every row in the table.
With references to the bare column, that allows MySQL to make use of an index, if a suitable index is available.
e.g.
SELECT e.*
FROM tabl.error_logs e
WHERE e.created_at >= DATE(NOW()) + INTERVAL -3 DAY
AND e.created_at < DATE(NOW()) + INTERVAL -2 DAY
note that we can easily test those expressions in the WHERE clause, to verify they are returning what we want, and tweak as necessary:
SELECT DATE(NOW()) + INTERVAL -3 DAY
, DATE(NOW()) + INTERVAL -2 DAY
To make your query sargable, you need ...
SELECT *
FROM tabl.error_logs
WHERE created_at >= DATE_SUB(CURDATE(), INTERVAL 3 DAY)
AND created_at < DATE_SUB(CURDATE(), INTERVAL 2 DAY)
This selects all values of created_at on or after midnight three days ago, up to but not including < midnight two days ago. It uses a range scan on an index on created_at if one is available.
You coudl use date_sub()
SELECT *
FROM tabl.error_logs
where date(created_at) = DATE_SUB(date(now()), INTERVAL 3 DAY);
if the column created_at is a date then you could avoid the date() function and let the index (if present) work for this column
SELECT *
FROM tabl.error_logs
where created_at = DATE_SUB(date(now()), INTERVAL 3 DAY);

How to convert timezone in a MySQL query?

I have the query that gets the data for the previous month. However, the time stored in the tables are in UTC (+00:00).
How do I adjust the query to convert the TimeZone from UTC to Australia/Sydney (+10:00) in the query?
My query is:
SELECT
DATE_FORMAT(pr.start_date,'%b %y') as start,
p.name as publisher,
sum(ifnull(pr.revenue,0)) as revenue
FROM trk.publisher_revenue pr
left outer join publisher p on p.pubid = pr.pubid
where pr.start_date between DATE_SUB(DATE_FORMAT(NOW() ,'%Y-%m-01'),
INTERVAL 1 MONTH) AND DATE_FORMAT(NOW() ,'%Y-%m-01')
and pr.status = 1
group by DATE_FORMAT(pr.start_date,'%b %y'),pr.pubid
order by pr.start_date, p.pubid;
The column where the date are stored is the start_date. It has the datatype DATETIME and the format it is stored is in e.g. 2014-09-01 00:00:00
The only solution for my problem is to adjust the query.
Desired result: Display the data, after converting the TimeZone to 'Australia/Syndey' or GMT +10:00.
It looks like you're trying to get your month boundaries right for a reporting query.
Your start_date values are stored in DATETIME data items, so you can convert them to UTC+10:00 like this:
pr.start_date + INTERVAL 10 HOUR
Simply rewrite your code to do that. For example, you can get the month in which each row falls with this expression:
DATE_FORMAT(pr.start_date + INTERVAL 10 HOUR,'%b %y')
But, there's a complication. The value of the expression NOW() depends on your MySQL connection's current time zone setting. This makes a difference for your range selection. If your time zone setting is UTC, you should apply the same ten-hour offset to NOW() and related values. For example, rewriting the query in your question, you'd get this:
where pr.start_date + INTERVAL 10 HOUR
between
DATE_FORMAT(NOW() + INTERVAL 10 HOUR ,'%Y-%m-01') - INTERVAL 1 MONTH
and /* WRONG ! */
DATE_FORMAT(NOW() + INTERVAL 10 HOUR ,'%Y-%m-01')
But, you really can't use BETWEEN for date ranges because it includes the end-date of the range, and you want to exclude that. So your date-selection query should be
where pr.start_date + INTERVAL 10 HOUR >=
DATE_FORMAT(NOW() + INTERVAL 10 HOUR ,'%Y-%m-01') - INTERVAL 1 MONTH
and pr.start_date + INTERVAL 10 HOUR <
DATE_FORMAT(NOW() + INTERVAL 10 HOUR ,'%Y-%m-01')
Notice the use of >= for the start of the date range and < for the end.
You probably should refactor that expression so it can exploit a range scan.
where pr.start_date >=
(DATE_FORMAT(NOW() + INTERVAL 10 HOUR ,'%Y-%m-01') - INTERVAL 1 MONTH)
- INTERVAL 10 HOUR
and pr.start_date <
(DATE_FORMAT(NOW() + INTERVAL 10 HOUR ,'%Y-%m-01'))
- INTERVAL 10 HOUR
It looks like there's a lot of redundant adding and subtracting of ten hours going on, but it's necessary because of the date-truncation in the middle of things.
Finally, I believe Sydney's daylight savings time zone, presently in effect, is UTC +11:00 not UTC + 10:00. You might want to double check your offset.

Data from current date to 30 days after current days

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);

Select records from NOW() -1 Day

Is there a way in a MySQL statement to order records (through a date stamp) by >= NOW() -1 so all records from the day before today to the future are selected?
Judging by the documentation for date/time functions, you should be able to do something like:
SELECT * FROM FOO
WHERE MY_DATE_FIELD >= NOW() - INTERVAL 1 DAY
Be aware that the result may be slightly different than you expect.
NOW() returns a DATETIME.
And INTERVAL works as named, e.g. INTERVAL 1 DAY = 24 hours.
So if your script is cron'd to run at 03:00, it will miss the first three hours of records from the 'oldest' day.
To get the whole day use CURDATE() - INTERVAL 1 DAY. This will get back to the beginning of the previous day regardless of when the script is run.
Didn't see any answers correctly using DATE_ADD or DATE_SUB:
Subtract 1 day from NOW()
...WHERE DATE_FIELD >= DATE_SUB(NOW(), INTERVAL 1 DAY)
Add 1 day from NOW()
...WHERE DATE_FIELD >= DATE_ADD(NOW(), INTERVAL 1 DAY)
You're almost there: it's NOW() - INTERVAL 1 DAY
Sure you can:
SELECT * FROM table
WHERE DateStamp > DATE_ADD(NOW(), INTERVAL -1 DAY)
when search field is timestamp and you want find records from 0 hours yesterday and 0 hour today use construction
MY_DATE_TIME_FIELD between makedate(year(now()), date_format(now(),'%j')-1) and makedate(year(now()), date_format(now(),'%j'))
instead
now() - interval 1 day