mysql生日提醒,闰年

时间:2010-02-08 19:49:30

标签: mysql leap-year

我正在尝试整理一个结果集,该结果集为按即将到来的生日排序的5个最近的用户排序。这种方法非常有效,直到闰年发挥作用。例如:

  • 5月15日 - 还剩96天
  • 5月15日 - 还剩97天

最重要的结果是1987年出生,而较低的是1988年。 u_birth存储为yyyy-mm-dd。 是否有一种简单的方法可以对此问题进行排序而无需重写整个查询?

SELECT u_birth, IF( DAYOFYEAR( u_birth ) >= DAYOFYEAR( NOW() ), 
          DAYOFYEAR( u_birth ) - DAYOFYEAR( NOW() ), 
          DAYOFYEAR( u_birth ) - DAYOFYEAR( NOW() ) +  
      DAYOFYEAR( CONCAT( YEAR( NOW() ), '-12-31' ) ) 
 )  
 AS distance
FROM (blog_users)
WHERE `s_agehide` = 0
ORDER BY distance ASC
LIMIT 5

此查询是从mysql手册中获取并修改的:http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#c7489

4 个答案:

答案 0 :(得分:8)

如果您的算法取决于该人的出生年份,则显然存在问题。要解决此问题,首先在当前日期之后找到每个人的下一个生日,然后计算该日期与现在之间的差异。

SELECT u_birth, DATEDIFF(next_birthday, NOW()) AS distance FROM (
    SELECT *, ADDDATE(birthday, INTERVAL birthday < DATE(NOW()) YEAR) AS next_birthday
    FROM (
        SELECT *, ADDDATE(u_birth, INTERVAL YEAR(NOW()) - YEAR(u_birth) YEAR) AS birthday
        FROM blog_users
        WHERE s_agehide = 0
    ) AS T1
) AS T2
ORDER BY distance ASC
LIMIT 5

结果:

'1992-02-29', 20
'1993-03-01', 21
'1987-05-15', 96
'1988-05-15', 96
'1988-09-18', 222

测试数据:

CREATE TABLE blog_users (u_birth NVARCHAR(100) NOT NULL, s_agehide INT NOT NULL);
INSERT INTO blog_users (u_birth, s_agehide) VALUES
('1987-05-15', 0),
('1988-05-15', 0),
('1988-09-20', 0),
('2000-01-02', 0),
('2000-01-03', 1),
('1988-09-19', 0),
('1988-09-18', 0),
('1992-02-29', 0),
('1993-03-01', 0);

请注意,在闰日出生的人假定在非闰年有2月28日的生日。

此外,您的查询不包含用户的用户ID。你可能想要添加它,我想。

答案 1 :(得分:2)

SELECT
    CONCAT(
        YEAR(CURRENT_DATE()),
        '-',
        DATE_FORMAT((birthDate),
            '%m-%d'
        )
    ),
    fullName
FROM
    employees
WHERE
    birthDate != 0
AND(
    CONCAT(
        YEAR(CURRENT_DATE())+ 1,
        '-',
        DATE_FORMAT((birthDate),
            '%m-%d'
        )
    )BETWEEN CURRENT_DATE()
    AND DATE_ADD(
        CURRENT_DATE(),
        INTERVAL 21 DAY
    )
    OR CONCAT(
        YEAR(CURRENT_DATE()),
        '-',
        DATE_FORMAT((birthDate),
            '%m-%d'
        )
    )BETWEEN CURRENT_DATE()
    AND DATE_ADD(
        CURRENT_DATE(),
        INTERVAL 21 DAY
    )
)

ps: birthDate 是我存储员工出生日期的列。 员工是表名。

答案 2 :(得分:1)

2月29日之后的闰年比平常更进一步,不要使用dayofyear。相反,提取月和日,并将它们与今天的年份结合在一起。然后做比较。

像这样:

SELECT u_birth, 
  IF(DATE(CONCAT(YEAR(NOW()),'-',MONTH(u_birth),'-',DAY(u-birth))) >= DATE(NOW()),
...

ETA:

因此我不必重写用于将出生日期转换为生日的表达式,我会将其粘贴在变量中。我建议您编写一个执行转换的函数,以便您可以直接在查询中使用它。

SET @birthday= SELECT DATE(CONCAT(YEAR(NOW()),'-',MONTH(u_birth),'-',DAY(u-birth))) FROM users WHERE user_id=x; //obviously only good for one value, but use the example for the calculation

SELECT u_birth, 
       IF(DATE(@birthday)>=DATE(NOW()), 
          DATEDIFF(DATE_ADD(@birthday, INTERVAL 1 YEAR),NOW()), 
          DATEDIFF(NOW(),@birthday)
       ) as days
FROM users WHERE user_id=x;

答案 3 :(得分:1)

也许有人会受到这种代码和平的启发。

它在我的案例中完美地运作但我认为有很多日期计算...

SELECT CONCAT(YEAR(CURRENT_DATE()),'-',DATE_FORMAT( FROM_UNIXTIME(date_of_birth), '%m-%d' )), fe_users.* 
FROM `fe_users`
WHERE `date_of_birth` != 0 AND (
     CONCAT(YEAR(CURRENT_DATE())+1,'-',DATE_FORMAT( FROM_UNIXTIME(date_of_birth), '%m-%d' )) BETWEEN CURRENT_DATE() AND DATE_ADD(CURRENT_DATE(), INTERVAL 7 DAY)
     OR
     CONCAT(YEAR(CURRENT_DATE()),'-',DATE_FORMAT( FROM_UNIXTIME(date_of_birth), '%m-%d' )) BETWEEN CURRENT_DATE() AND DATE_ADD(CURRENT_DATE(), INTERVAL 7 DAY)
)

通过SQL-Code的这种和平,您将获得表fe_users的所有用户,其date_of_birth(保存为unix-timestamp)将在接下来的7天内。您可以通过更改date_add()函数使用的时间间隔,将其扩展为21天。