Sort upcoming birthdays based on current date

后端 未结 5 945
庸人自扰
庸人自扰 2020-12-06 08:01

I have the following table of people and their birthdays:

name        birthday
----------------------
yannis      1979-06-29
natalia     1980-08-19
kostas            


        
相关标签:
5条回答
  • 2020-12-06 08:21

    Here is one way:

    • Calculate current year - year of birth
    • Add the resulting number of years to the date of birth
    • You now have the birthday this year, if this date has passed then add one more year
    • Sort the results by that date
    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
    

    Notes:

    • Today's birthdays appears first regardless of current time
    • February 29 birthday is treated equal to February 28 birthday for common years e.g.
      • On Jan/1/2019 both Feb 28 and Feb 29 birthdays (2019) are sorted equal
      • On Mar/1/2019 Feb 28 and Feb 29 birthdays (2020) are sorted as expected

    SQLFiddle

    0 讨论(0)
  • 2020-12-06 08:23

    Not pretty, but works

    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
    
    0 讨论(0)
  • 2020-12-06 08:26

    Seems to be rather fast, no problems with leap years:

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

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

    0 讨论(0)
  • 2020-12-06 08:30
    SELECT name
         , birthday
    FROM TableX
    ORDER BY DAYOFYEAR(birthday) < DAYOFYEAR(CURDATE())
           , DAYOFYEAR(birthday)
    

    No, the above may produce error results, due to years with 366 days. This is correct:

    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
    

    If your table grows to more than a few thousands records, it will be real slow. If you want a fast query, add fields with the month and day and have an index on (bmonth,bday) or add them as one field, either Char (08-17 or 0817 for 17-Aug) or Int (817 for 17-Aug) and an index on that field.

    0 讨论(0)
  • 2020-12-06 08:35

    i would try it like this (but this isn't tested):

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

    EDIT:
    changed ordering from DESC to ASC because you want to get the farthest first, not the closest.

    0 讨论(0)
提交回复
热议问题