I have the following table of people and their birthdays:
name birthday
----------------------
yannis 1979-06-29
natalia 1980-08-19
kostas
Here is one way:
SELECT
name,
birthday,
birthday + INTERVAL (YEAR(CURRENT_DATE) - YEAR(birthday)) YEAR AS currbirthday,
birthday + INTERVAL (YEAR(CURRENT_DATE) - YEAR(birthday)) + 1 YEAR AS nextbirthday
FROM birthdays
ORDER BY CASE
WHEN currbirthday >= CURRENT_DATE THEN currbirthday
ELSE nextbirthday
END
Notes:
SQLFiddle
Not pretty, but works
SELECT *
,CASE WHEN BirthdayThisYear>=NOW() THEN BirthdayThisYear ELSE BirthdayThisYear + INTERVAL 1 YEAR END AS NextBirthday
FROM (
SELECT *
,birthday - INTERVAL YEAR(birthday) YEAR + INTERVAL YEAR(NOW()) YEAR AS BirthdayThisYear
FROM bd
) AS bdv
ORDER BY NextBirthday
Seems to be rather fast, no problems with leap years:
SELECT *
FROM `people`
ORDER BY CONCAT(SUBSTR(`birthday`,6) < SUBSTR(CURDATE(),6), SUBSTR(`birthday`,6))
Все гениальное -- просто! ;)
SELECT name
, birthday
FROM TableX
ORDER BY DAYOFYEAR(birthday) < DAYOFYEAR(CURDATE())
, DAYOFYEAR(birthday)
No, the above may produce error results, due to years with 366 days. This is correct:
SELECT name
, birthday
FROM
( SELECT name
, birthday
, MONTH(birthday) AS m
, DAY(birthday) As d
FROM TableX
) AS tmp
ORDER BY (m,d) < ( MONTH(CURDATE()), DAY(CURDATE()) )
, m
, d
If your table grows to more than a few thousands records, it will be real slow. If you want a fast query, add fields with the month and day and have an index on (bmonth,bday) or add them as one field, either Char (08-17 or 0817 for 17-Aug) or Int (817 for 17-Aug) and an index on that field.
i would try it like this (but this isn't tested):
SELECT
name,
birthday
FROM
birthdays
ORDER BY
ABS( DAYOFYEAR(birthday) - (DAYOFYEAR(CURDATE()) ) ASC
EDIT:
changed ordering from DESC to ASC because you want to get the farthest first, not the closest.