SELECT u.*, CAST(CONCAT_WS('.', YEAR(SYSDATE()) + (CAST(CONCAT_WS('.', YEAR(SYSDATE()), month, day) AS DATE) < SYSDATE()), month, day) AS DATE) AS nbd
FROM t_users u
ORDER BY
nbd;
The ORDER BY
expression takes the boolean result of the comparison of the current year's birthday to the current date and adds it to the current year.
This results in the next birthday (expressed as DATE
) on which the statement can be ordered by.
As a bonus, you can easily get this next birthday:
5, 'jane', 1975, 9, 22, '2009-09-22'
3, 'bob', 1985, 2, 14, '2010-02-14'
4, 'joe', 1964, 2, 16, '2010-02-16'
1, 'john', 1978, 5, 1, '2010-05-01'
2, 'mike', 1979, 7, 23, '2010-07-23'
Update:
This query handles leap years better.
SELECT u.*, CAST(CONCAT_WS('.', year, month, day) AS DATE),
CAST(CONCAT_WS('.', 1980, month, day) AS DATE) + INTERVAL YEAR(SYSDATE()) - 1980 YEAR +
INTERVAL CAST(CONCAT_WS('.', 1980, month, day) AS DATE) + INTERVAL YEAR(SYSDATE()) - 1980 YEAR < SYSDATE() YEAR AS nbd
FROM t_users u
ORDER BY
nbd;
It assumes that the non leap-year birthday for a person born on Feb 29
is Feb 28
.
I added a person named Alex
who was born on Feb 29, 1980
:
5, 'jane', 1975, 9, 22, '1975-09-22', '2009-09-22'
3, 'bob', 1985, 2, 14, '1985-02-14', '2010-02-14'
4, 'joe', 1964, 2, 16, '1964-02-16', '2010-02-16'
6, 'alex', 1980, 2, 29, '1980-02-29', '2010-02-28'
1, 'john', 1978, 5, 1, '1978-05-01', '2010-05-01'
2, 'mike', 1979, 7, 23, '1979-07-23', '2010-07-23'