给出下面的mysql表:
ID|name|year|month|day
----------------------
1 |john|1978|5|1
2 |mike|1979|7|23
3 |bob |1985|2|14
4 |joe |1964|2|16
5 |jane|1975|9|22
我正在尝试按照他们的生日事件,即将到来的生日顺序提取用户。 因此,如果查询在9月16日执行,则顺序应为:jane,bob,joe,john,mike。
答案 0 :(得分:8)
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;
ORDER BY
表达式采用当前年份的生日与当前日期的比较的布尔结果,并将其添加到当前年份。
这导致下一个生日(表示为DATE
),可以在其上订购该声明。
作为奖励,您可以轻松获得下一个生日:
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'
<强>更新强>
此查询可以更好地处理闰年。
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;
它假设Feb 29
出生的人的非闰年生日为Feb 28
。
我添加了一个名为Alex
的人,他出生于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'
答案 1 :(得分:2)
如果您将生日存储为日期对象,则可以使用:
SELECT *
FROM BirthdayTable
ORDER BY dayofyear(birthdayDateColumn - INTERVAL dayofyear(now()) -1 DAY)
或者,将日期字段分开,我认为您可以使用以下内容:
SELECT *
FROM BirthdayTable
ORDER BY dayofyear(cast(CONCAT_WS("-", year, month, day) as date) - INTERVAL dayofyear(now()) -1 DAY)
这些ORDER BY语句根据当年的生日(一年中的当天)对生日进行排序,以便从每个生日的今天开始订购。
答案 2 :(得分:1)
我本可以将出生日期存储在日期格式中,但请注意,尝试做这样的事情 - 选择所有出生日期转换为下一个生日日期的人,然后对此进行排序。使用STR_TO_DATE
在MySQL中使用任意字符串创建日期很容易。然后,您只需要执行IF
语句来选择正确的年份。尝试这样的事情:
SELECT * FROM (
SELECT name, IF(
STR_TO_DATE(CONCAT(YEAR(NOW()), '-', month, '-', day)) < NOW(),
STR_TO_DATE(CONCAT(YEAR(NOW())+1, '-', month, '-', day)),
STR_TO_DATE(CONCAT(YEAR(NOW()), '-', month, '-', day))) AS next_birthday
FROM people) as next_birthdays
ORDER BY next_birthday;
我认为应该这样做。当然,如果您有一个DATE类型的生日列,那会更容易。
答案 3 :(得分:1)
最优雅的解决方案是完全忽略年限。无需将任何内容转换为日期类型即可执行排序。
相反,创建一个排序键,假设所有月份都是31天(最大值)。当月份未来时,添加月* 31天。在过去,加上一年加。然后为当天添加偏移量。
对于当月,请查看当月的日期,并执行相同的操作:如果将来添加它。如果没有,请加上12“长”(31天)的月份。
此解决方案可在闰年中正常运行,无需将各个字段转换为日期。
SELECT * FROM mytable ORDER BY
CASE
/* Month has passed this year, sort key considers it a "long year" further in the future) */
WHEN month - MONTH(NOW()) < 0 THEN (month+12) * 31 + day
/* Month has not passed year, sort key is a "long month" + days in the future */
WHEN month - MONTH(NOW()) > 0 THEN month * 31 + day
/* Same month, so we have to compare based on the day of the month */
ELSE
CASE
WHEN day - DAY(NOW()) < 0 THEN day + (12*31)
ELSE day
END CASE
END CASE
答案 4 :(得分:0)
SELECT *
FROM table
ORDER BY CASE WHEN month*100+day > MONTH(getdate())*100+DAY(getdate())
THEN (month - MONTH(getdate()))*100 + day - DAY(getdate())
ELSE (12 + month - MONTH(getdate()))*100 + day - DAY(getdate())
END
答案 5 :(得分:0)
这是一种方式
select *
from foo
order by
if ( (dayofyear(concat(year(now()),'-',month,'-',day))-dayofyear(now())) < 0,
(dayofyear(concat(year(now()),'-',month,'-',day))-dayofyear(now()))+365,
(dayofyear(concat(year(now()),'-',month,'-',day))-dayofyear(now()))
);
基本上,它按照直到今年生日的天数排序,除非是过去的情况,在这种情况下,它会再添加365天来查看它到底有多少天。
答案 6 :(得分:-2)
所以索引只涉及一个字段
ID|name|year|month|day|orderextrac
----------------------
1 |john|1978|5|1 |19780501
2 |mike|1979|7|23 |19790723
3 |bob |1985|2|14 |19850214
4 |joe |1964|2|16 |19640216
5 |jane|1975|9|22 |19750922
select name from table1 order orderextrac