【问题标题】:Sort upcoming birthdays based on current date根据当前日期对即将到来的生日进行排序
【发布时间】:2011-09-08 06:10:44
【问题描述】:

我有下表中的人员及其生日:

name        birthday
----------------------
yannis      1979-06-29
natalia     1980-08-19
kostas      1983-10-27    
christos    1979-07-22
kosmas      1978-04-28

而且我不知道如何根据生日与今天的距离对名字进行排序。所以对于 NOW() = 2011-09-08,排序结果应该是:

kostas      1983-10-27
kosmas      1978-04-28
yannis      1979-06-29
christos    1979-07-22
natalia     1980-08-19

我正在寻找一种快速的技巧,并不真正关心性能(宠物项目 - 表将容纳少于 1000 条记录),但当然每一个建议都会非常感谢。

【问题讨论】:

  • @ajreal 她的生日在 8 月,所以她必须等待最长时间才能参加派对 :)
  • 好的,所以您希望即将到来的个生日按最接近今天的生日排序?
  • @Salman Yes :) 编辑了标题,希望现在更清楚
  • 我在您接受后编辑了我的答案。原始答案与闰年有问题。

标签: mysql sql sorting date datetime


【解决方案1】:

这是一种方法:

  • 计算当年 - 出生年份
  • 将得到的年数添加到出生日期
  • 你现在有今年的生日,如果这个日期已经过去,那么再增加一年
  • 按该日期对结果进行排序
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

注意事项:

  • 无论当前时间如何,今天的生日都会首先出现
  • 2 月 29 日生日被视为与 2 月 28 日生日相同,例如普通年份。
    • 在 2019 年 1 月 1 日,2 月 28 日和 2 月 29 日的生日(2019 年)排序相同
    • 2019 年 3 月 1 日和 2 月 28 日和 2 月 29 日生日(2020 年)按预期排序

SQLFiddle

【讨论】:

    【解决方案2】:
    SELECT name
         , birthday
    FROM TableX
    ORDER BY DAYOFYEAR(birthday) < DAYOFYEAR(CURDATE())
           , DAYOFYEAR(birthday)
    

    不,以上可能会产生错误结果,因为年份是 366 天。这是正确的:

    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
    

    如果您的表增长到超过几千条记录,那将会非常缓慢。如果您想要快速查询,请添加带有月份和日期的字段,并在(bmonth,bday) 上有一个索引,或者将它们添加为一个字段,可以是 Char(08-17 或 0817 用于 17-Aug)或 Int(817 8 月 17 日)和该字段的索引。

    【讨论】:

    • 第一次查询有拒绝的例子吗?
    • @Hafez “拒绝”是什么意思?
    【解决方案3】:

    似乎相当快,闰年没有问题:

    SELECT * 
    FROM `people` 
    ORDER BY CONCAT(SUBSTR(`birthday`,6) < SUBSTR(CURDATE(),6), SUBSTR(`birthday`,6))
    

    Все гениальное -- просто! ;)

    【讨论】:

      【解决方案4】:

      不漂亮,但有效

      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
      

      【讨论】:

        【解决方案5】:

        我会这样尝试(但未经测试):

        SELECT
          name,
          birthday
        FROM
          birthdays
        ORDER BY
          ABS( DAYOFYEAR(birthday) - (DAYOFYEAR(CURDATE()) ) ASC
        

        编辑:
        将排序从DESC 更改为ASC,因为您想先获得最远的,而不是最近的。

        【讨论】:

        • 我认为这不能正常工作。昨天过生日的用户会显示在接近顶部的位置,我认为这不是我们想要的。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-12
        • 1970-01-01
        • 1970-01-01
        • 2019-06-17
        • 2020-10-15
        相关资源
        最近更新 更多