【问题标题】:Upcoming birthdays year bug (SQL)即将到来的生日年错误 (SQL)
【发布时间】:2014-10-21 22:04:35
【问题描述】:

这是我当前的 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 天的限制。

标签: mysql sql


【解决方案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,我在第二个查询中对此进行了更正。 如果你存储未来的生日,你会得到一个更快(和更容易)的查询。
  • @Johan,抱歉,我无法运行查询号。二。杂散分号,ORDER BY 和“NOW”中缺少括号,而不是“NOW()”。可以编辑吗?
  • @Johan 我发现您的订单查询有问题。如果是 6 月 15 日怎么办... 6 月前几天(或前几个月)的所有结果都将出现在 12 月生日之前的结果中。对这件事有什么想法吗?
【解决方案2】:

我相信您需要使用包含年份的东西来订购。

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

我不是专家,但类似的方法也可以。

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

【讨论】:

  • 第二个是对的。首先它按年份排序结果,即(2009、2010、2011),然后按年份按月排序,然后按月按天排序。
  • 那行不通。年份可以是 1989 年、1974 年、1990 年……查询应该担心的年份是当前年份和下一个年份。
【解决方案3】:

我想你想知道每个用户的生日,被带到今年还是下一年,是否在你的范围内:

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,特别是如果您打算在每个月的第一天运行此查询。)

【讨论】:

    【解决方案4】:

    您的查询将创建全表扫描。

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

    【讨论】:

      【解决方案5】:

      我一直在搜索此代码,但找不到干净/简单的查询(也适用于闰年(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)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-10
        • 1970-01-01
        • 2011-04-14
        • 1970-01-01
        • 2014-05-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多