Reputation: 4401
My MySQL database table has dates stored in the MySQL format (YYYY-MM-DD). I need to construct an SQL query that will return rows with dates that either occur today or yesterday or a day before. For example, if the stored date is 1979-08-22, I would like this row returned if today is 8/22 (the same date in a different year) or 8/23 or 8/24.
I'm thinking of using the DAYOFYEAR() function, which returns a single value between 1 and 365 depending on the date. Here is the current query:
SELECT * FROM `theTable` WHERE DAYOFYEAR(CURDATE())-DAYOFYEAR(`theDate`) IN(0, 1, 2, -364, -363)
This query finds the difference in days between the current date and the stored date and if it's 3 days, it should return the result. It seems to work.
Is this the right way to achieve the result I want or is there another, more efficient way? Is this likely to cause issues with leap years?
Upvotes: 1
Views: 475
Reputation: 4401
SELECT * FROM `datesTable`
WHERE (
MONTH(`theDate`) = MONTH(CURDATE())
AND DAY(`theDate`) = DAY(CURDATE())
) OR (
MONTH(`theDate`) = MONTH(DATE_ADD(CURDATE(), INTERVAL -1 DAY))
AND DAY(`theDate`) = DAY(DATE_ADD(CURDATE(), INTERVAL -1 DAY))
) OR (
MONTH(`theDate`) = MONTH(DATE_ADD(CURDATE(), INTERVAL -2 DAY))
AND DAY(`theDate`) = DAY(DATE_ADD(CURDATE(), INTERVAL -2 DAY))
)
Done!
Upvotes: 0
Reputation: 4682
Does it specifically have to be today, yesterday, or the day before - or the last 72 hours is also okay?
SELECT * FROM foo WHERE UNIX_TIMESTAMP(field) BETWEEB CURRENT_TIMESTAMP - 259200 AND CURRENT_TIMESTAMP
update It seems like I completly missed the part about the years being different... another possible solution (which works on days diff and not hours) which I added as a comment is WHERE DATEDIFF(DATE_FORMAT(CURDATE(), '1990-%m-%d'), DATE_FORMAT(field, '1990-%m-%d')) <= 2
Upvotes: 1
Reputation: 3722
This seems harder than it needs to be. What's wrong with something like:
WHERE thedate >= DATE_SUB(CURRENT_DATE(), INTERVAL 2 DAY)
If future dates are possible you will require an additional clause: AND thedate <= CURRENT_DATE()
Treating dates like strings and trying to do math is wrought of peril. Leap years, leap seconds, edge cases over year ends, etc. all cause problems. If there's a built in library capable of solving your problem you're much better off using it, rather than rolling your own.
Upvotes: 1
Reputation: 1603
If you use mysql function on where clause, the optimizer can't use the index on that field (if there is an index on it)
You can check how the optimizer is going to treat your query with the EXPLAIN command
EXPLAIN SELECT * FROM `theTable` WHERE DAYOFYEAR(CURDATE())-DAYOFYEAR(`theDate`) IN(0, 1, 2, -364, -363)
If the table is small and will not grow and your not concerned about performance you should not worry.
Me I would add a new VARCHAR field beside the DATETIME field and I would store the same information in this field but in a different order
DATETIME: 2011-01-01
VARCHAR: 01-01-2011
And I would create an index on the varchar field, this way you could run fast and easy extraction query like
SELECT * FROM `theTable` WHERE `varchar_date` LIKE '01-01-%'
Upvotes: 1
Reputation: 56357
select *,
if(right(date_field,5)<=right(curdate(),5),concat(year(curdate()),'-',right(date_field,5)),concat(year(curdate() - interval 1 year),'-',right(date_field,5))) as myfield
from table
having myfield between curdate() - interval 2 day and curdate()
Upvotes: 1