即将到来的生日年份错误(SQL)

3

这是我当前的 SQL 查询,用于获取我们公司未来 90 天内所有即将过生日的员工:

 SELECT
   user.birthday, user.name, MONTH(user.birthday)
   AS month, DAY(user.birthday) AS day
 FROM user WHERE
   (1 =
   (FLOOR(DATEDIFF(DATE_ADD(DATE(NOW()),INTERVAL
   90 DAY),birthday) / 365.25)) -
   (FLOOR(DATEDIFF(DATE(NOW()),birthday)
   / 365.25))) 
 ORDER BY MONTH(birthday),DAY(birthday)

问题在于,如果现在是11月,而一些生日是在1月份,它将首先显示1月份的生日,然后是11月和12月,尽管今年已经过了1月份的生日。

是否有一种方法可以在同一个SQL查询中重新排序这些记录,以便首先显示当前和未来的月份,然后再显示明年的月份?

感谢Johan提供的第一个部分解决方案。

ORDER BY ( MONTH(birthday) > MONTH(NOW()             
        OR ((MONTH(birthday) = MONTH(now()) 
            AND DAY(birthday) >= DAY(NOW()) DESC
   , MONTH(birthday), DAY(birthday) 

还需要一点改进。如果生日已经过去,它应该显示在12月之后的结果中。假设今天是6月27日,则应该显示以下示例:

  • 6月28日:约翰·多
  • 12月27日:玛丽·莱特
  • 明年6月5日:疯狂的麦克斯

明年的6月5日不会被选中,因为它不在90天的限制范围内。 - Johan
5个回答

1

我不确定,但似乎你的生日包括年份。如果是这样,那么每个用户将有一系列生日(每年一个),您可以选择在接下来的90天内的生日。

SELECT
  user.birthday
  , user.name
  , MONTH(user.birthday) AS month
  , DAY(user.birthday) AS day  
FROM user 
WHERE  birthday BETWEEN NOW() AND DATE_ADD(NOW, INTERVAL 90 DAY)  
ORDER BY Birthday DESC

如果你的生日只有月份和日期,那么你的查询应该是:
SELECT
  user.birthday
  , user.name
  , MONTH(user.birthday) AS month
  , DAY(user.birthday) AS day  
FROM user 
WHERE STR_TO_DATE(CONCAT(YEAR(NOW()),MONTH(birthday),DAY(birthday)),'%YYYY%M%D')
  BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 90 DAY) OR
STR_TO_DATE(CONCAT(YEAR(DATE_ADD(NOW(),INTERVAL 1 YEAR)),MONTH(birthday),DAY(birthday)),'%YYYY%M%D')
  BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 90 DAY) 
ORDER BY ( MONTH(birthday) > MONTH(NOW() 
           OR ((MONTH(birthday) = MONTH(now()) AND DAY(birthday) >= DAY(NOW()) DESC,
         MONTH(birthday), DAY(birthday)

但是可以肯定的是,OP的user.birthdate是用户的历史出生日期,而不是每个用户即将到来的生日。(因此在年份间隔计算中使用FLOOR()代码。) - pilcrow
@pilcrow,我在第二个查询中进行了更正。如果你存储未来的生日,你将获得一个更快(和更容易)的查询。 - Johan
@Johan,抱歉,我无法运行第二个查询。ORDER BY中有分号错误、括号缺失以及使用了“NOW”而非“NOW()”。你能否编辑一下? - pilcrow
@Johan,我发现你的订单查询有一个问题。如果是6月15日呢...那么6月之前(或之前几个月)的所有结果都将出现在12月生日的结果之前。对此有什么想法吗? - Andres SK
哦,现在我明白了,呵呵,你修改了原帖。现在它可以工作了,并且解决了那个特定的问题。再次感谢! - Andres SK
显示剩余3条评论

1

我想你想知道每个用户的生日,是在今年或明年,是否落在你的范围内:

SELECT name, birthday
  FROM (SELECT name, birthday, YEAR(NOW()) - YEAR(birthday) AS years_ago
          FROM user) d
 WHERE DATE_ADD(birthday, INTERVAL years_ago YEAR)
           BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 90 DAY)
       OR
       DATE_ADD(birthday, INTERVAL (years_ago + 1) YEAR)
           BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 90 DAY);

我想你可能需要 INTERVAL 3 MONTH,而不是 90 DAY,特别是如果你打算在每月的第一天运行这个查询。


1

我相信你需要使用包含年份的某些内容来进行排序。

ORDER by date_format( date, "%d/%m/%Y" )

虽然我不是专家,但这种方法也可能行得通。

ORDER BY YEAR(birthday),MONTH(birthday),DAY(birthday)

第二个是正确的。首先按年份排序结果,即(2009、2010、2011),然后按年份中的月份排序,最后按月份中的日期排序。 - cypher
那是行不通的。年份可能是1989年、1974年、1990年...查询应该只关心当前和下一个年份。 - Andres SK

0
我一直在寻找这段代码,但我找不到一个简洁/简单的查询(也适用于闰年(2月29日的问题))
所以我自己写了一个。
这是获取接下来 x 天内即将到来的生日的最简代码(此查询还显示昨天的生日(或者您可以将其更改为过去 x 天的生日)。
SELECT name, date_of_birty 
FROM users 
WHERE DATE(CONCAT(YEAR(CURDATE()), RIGHT(date_of_birty, 6)))
        BETWEEN 
            DATE_SUB(CURDATE(), INTERVAL 1 DAY)
        AND
            DATE_ADD(CURDATE(), INTERVAL 5 DAY)

0

您的查询将创建一个完整的表扫描。

存储一个包含一年中的日期(4月1日左右为第90天)的整数,并将其与当前的一年中的日期进行比较。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接