【问题标题】:calculate age in years months and days以年月和日计算年龄
【发布时间】:2013-09-12 06:07:21
【问题描述】:

我在 mysql 中使用 FROM_DAYS 函数时遇到问题,我想从 my_table 中获取年龄,这是我的查询;

select dob,CURRENT_DATE,
DATE_FORMAT(FROM_DAYS(DATEDIFF(CURRENT_DATE,dob)),'%y yr %c mth %e dy') AS age, 
DATEDIFF(CURRENT_DATE,dob) days from my_table

结果:

dob       || CURRENT_DATE || age              || days  ||
==========++==============++==================++=======++
1953-09-10|| 2013-09-12   || 60 yr 1 mth 3 dy || 21917 ||
2013-09-08|| 2013-09-12   || 00 yr 0 mth 0 dy ||     4 ||

当我在第二行尝试FROM_DAYS(DATEDIFF(CURRENT_DATE,m.tgllahir)) 时,结果是0000-00-00

然后我尝试查看Date and Time Functions 并找到了这个

SELECT FROM_DAYS(730669);
        -> '2007-07-03'

但是当我尝试时,这就是我得到的;

SELECT FROM_DAYS(730669);
        -> '2000-07-03'

我很好奇为什么FROM_DAYS 功能不能正常工作,但我的主要问题是如何找到年龄?

编辑

在与 Barmar 讨论后,我知道我无法使用 FROM_DAYS 来获得准确的年龄,所以我试图找到不同的方法

【问题讨论】:

  • @asharajay 和我的查询基本相同
  • 我认为这是文档中的错误。 730669/365.25 = 2000.46.
  • FROM_DAYS(n) 为所有 n < 366 返回 0000-00-00。文档说 在旧日期谨慎使用 FROM_DAYS()。它不适用于公历 (1582) 出现之前的值
  • FROM_DAYS() 将自 0 年以来的天数转换为日期。所以 366 是第 1 年 1 月的第一天,即 0001-01-01 - 日历中没有 00 月。我不知道为什么它在 0 年不起作用,但那一年是在 1582 年之前,所以文档说不要在这么旧的日期使用它。

标签: mysql sql date


【解决方案1】:
SELECT FLOOR(( DATE_FORMAT(NOW(),'%Y%m%d') - DATE_FORMAT(t.dob,'%Y%m%d'))/10000) AS years,
       FLOOR((1200 + DATE_FORMAT(NOW(),'%m%d') - DATE_FORMAT(t.dob,'%m%d'))/100) %12 AS months,
       (SIGN(DAY(NOW()) - DAY(t.dob))+1)/2 * (DAY(NOW()) - DAY(t.dob)) +
      (SIGN(DAY(NOW()) - DAY(t.dob))+1)/2 * (DAY(NOW()) - DAY(t.dob)) +
      (SIGN(DAY(t.dob) - DAY(NOW()))+1)/2 * (DAY(STR_TO_DATE(DATE_FORMAT(t.dob + INTERVAL 1 MONTH,'%Y-%m-01'),'%Y-%m-%d') - INTERVAL 1 DAY) - DAY(t.dob) + DAY(NOW())) AS days
 FROM tablename t

试试这个查询

【讨论】:

    【解决方案2】:

    这是我用来计算年龄的查询,以年、月和日为单位:

    SELECT 
    username
    ,dob
    ,DATE_FORMAT(CURDATE(), '%Y') - DATE_FORMAT(dob, '%Y') - (DATE_FORMAT(CURDATE(), '00-%m-%d') < DATE_FORMAT(dob, '00-%m-%d')) AS years
    ,PERIOD_DIFF( DATE_FORMAT(CURDATE(), '%Y%m') , DATE_FORMAT(dob, '%Y%m') ) AS months
    ,DATEDIFF(CURDATE(),dob) AS days
    FROM users
    

    【讨论】:

    • 最后,OP 可以继续他们的项目了
    【解决方案3】:

    要使用 FROM_DAYS() 函数并以您正在寻找的格式获取人的年龄,您必须简单地添加一个函数来获取年份月份或日期,就像这样

    CONCAT(
      YEAR(FROM_DAYS(DATEDIFF(NOW(),*DB LOCATION*))),' years,',
      MONTH(FROM_DAYS(DATEDIFF(NOW(),*DB LOCATION*))),' months,',
      DAY(FROM_DAYS(DATEDIFF(NOW(),*DB LOCATION*))),' days,',)
    

    【讨论】:

      【解决方案4】:

      我更喜欢使用函数。

      这是我的函数的 DDL。这个函数更准确更精确。

      DELIMITER $$ 
      DROP FUNCTION IF EXISTS f_age $$
      CREATE FUNCTION `f_age`(
              x_dob DATE
          )
          RETURNS varchar(100) CHARSET latin1
          NOT DETERMINISTIC
          CONTAINS SQL
      
      BEGIN
      DECLARE x_result VARCHAR(100);
      DECLARE y1, y2, m1, m2, d1, d2 INT;
      DECLARE x1, x2 DATE;
      
        SET x_result = "";
        SET x1 = x_dob;
        SET x2 = CURDATE();
      
        IF (x1 < x2) THEN
          SET y1 = DATE_FORMAT(x1, '%Y');
          SET m1 = DATE_FORMAT(x1, '%c');
          SET d1 = DATE_FORMAT(x1, '%e');
      
          SET y2 = DATE_FORMAT(x2, '%Y');
          SET m2 = DATE_FORMAT(x2, '%c');
          SET d2 = DATE_FORMAT(x2, '%e');
      
          IF (d1 > d2) THEN
              SET m2 = m2 - 1;
      
              IF (m2 = 0) THEN
                  SET y2 = y2 - 1;
                  SET m2 = 12;
              END IF;
      
              SET d2 = d2 + DAY(LAST_DAY(CONCAT_WS("-", y2, m2, d2)));
          END IF;
      
          IF (m1 > m2) THEN
              SET y2 = y2 - 1;
              SET m2 = m2 + 12;
          END IF;
      
          IF (y2 > y1) THEN
              SET x_result = CONCAT((y2 - y1), ' yr ');
          END IF;
      
          IF ((y2 > y1) OR (m2 > m1)) THEN
              SET x_result = CONCAT(x_result, CONCAT((m2 - m1), ' mth '));
          END IF;
      
          IF ((y2 > y1) OR (m2 > m1) OR (d2 > d1)) THEN
              SET x_result = CONCAT(x_result, CONCAT((d2 - d1), ' dy'));
          END IF;
        ELSE
          SET x_result = "Error. Date of birth is today or more than today";
        END IF;
      
        RETURN x_result;
      END $$
      
      DELIMITER ;
      

      然后,这里是使用该功能的代码:

      SELECT f_age(dob) FROM table;
      

      它还能准确处理闰年

      【讨论】:

      • 这个“更精确”在哪里?为什么您认为其他答案没有考虑闰年?
      • 嗨@nico,让我们尝试使用 Mark's 的答案,使用 Now() = 2018-01-25 和 dob = 2017-01-01,结果是 1 yr 1 mt 24 dy(这是真的),但是当我们更改 dob = 2016-01-01 时,结果将是 1 yr 1 mt 25 dy(这不是真的,因为 2016 年是闰年)。使用我的函数时,结果是 1 yr 1 mt 24 dy 和 2 yr 1 mt 24 dy(日期准确)
      • 如果在这两种情况下 NOW() = xx-01-01 和 dob = xx-01-01,则结果不应包含任何月份或日期...
      • 我的?是的,我认为年龄为零..所以当现在 = dob 时我跳过计算,你的意见是什么?
      • 这是对您算法的完全不必要的补充。不要让它变得更复杂,因为它需要是
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-25
      • 2011-06-10
      • 2010-09-08
      • 2021-05-16
      • 2010-10-01
      相关资源
      最近更新 更多