MAKEDATE()
creates a date from a year and the day of year, so I can use it to get old years out of the picture:
SELECT
anniversary
, MAKEDATE( YEAR(NOW()), DAYOFYEAR(anniversary) ) AS thisyear
FROM Anniversaries;
+-------------+-------------+
| anniversary | thisyear |
+-------------+-------------+
| 1978-07-29 | 2010-07-29 |
| 1959-04-17 | 2010-04-17 |
+-------------+-------------+
Then I can use DATEDIFF()
calculate the days until ( or from ) then:
SELECT
anniversary
, MAKEDATE( YEAR(NOW()), DAYOFYEAR(anniversary) ) AS thisyear
, DATEDIFF( MAKEDATE(YEAR(NOW()),DAYOFYEAR(anniversary)), NOW()) as days
FROM Anniversaries;
+-------------+-------------+------+
| anniversary | thisyear | days |
+-------------+-------------+------+
| 1978-07-29 | 2010-07-29 | 70 |
| 1959-04-17 | 2010-04-17 | -33 |
+-------------+-------------+------+
Assuming NOW() is 5/20.
Edit so the above doesn't work over year rollover. One solution is to add another calculation, where the anniversary is the next year. Here I've hard-coded the date '2010-12-31', and used an OR
in a HAVING
clause to filter by days that match either this year or next:
SELECT birth_date
, MAKEDATE(YEAR('2010-12-31'),DAYOFYEAR(birth_date)) as anniversary
, DATEDIFF( MAKEDATE(YEAR('2010-12-31'),DAYOFYEAR(birth_date)), '2010-12-31') as days
, MAKEDATE(YEAR(NOW())+ 1,DAYOFYEAR(birth_date)) as next_anniversary
, DATEDIFF( MAKEDATE(YEAR(NOW())+ 1,DAYOFYEAR(birth_date)), '2010-12-31') as next_days
FROM Anniversaries
HAVING ( ( days <= 25 AND days > 0 ) OR next_days <= 25 );
+------------+-------------+------+------------------+-----------+
| birth_date | anniversary | days | next_anniversary | next_days |
+------------+-------------+------+------------------+-----------+
| 2010-01-23 | 2010-01-23 | -342 | 2011-01-23 | 23 |
| 1975-01-11 | 2010-01-11 | -354 | 2011-01-11 | 11 |
+------------+-------------+------+------------------+-----------+
2 rows in set (0.00 sec)