【问题标题】:How to get an age from a D.O.B field in MySQL?如何从 MySQL 中的 DOB 字段中获取年龄?
【发布时间】:2011-02-01 19:07:27
【问题描述】:

我需要根据“客户”的出生日期计算其年龄。

我尝试使用以下内容:

DATEDIFF(year, customer.dob, "2010-01-01");

但它似乎不起作用。

有什么想法吗?我知道这会很简单!

谢谢

【问题讨论】:

    标签: mysql select date


    【解决方案1】:

    简单的方法:

    timestampdiff(YEAR,birth_date,now())AS 年龄

    【讨论】:

      【解决方案2】:

      如果你想要像“26 年 4 个月零 27 天”这样的年、月和日,那么以下是适合你的年龄函数:

      delimiter $$
      
      create function age(dob date)
      returns varchar(30)
      deterministic
      begin
      declare years int default 0;
      declare months int default 0;
      declare days int default 0;
      declare today date default curdate();
      
      set years = timestampdiff(year, dob, today);    
      set months = timestampdiff(month, dob, today - interval years year);    
      set days = timestampdiff(day, dob, today - interval years year - interval months month);
      
      return (concat(years, ' years ', months,' months and ', days,' days'));
      
      end$$
      
      delimiter;
      

      我们从当前日期开始计算年龄,所以我将今天设置为 curdate()。 现在我们的年月日如下所示。

      1. 年:我们得到从今天到出生日期的年差。

      2. 月: 首先,我们从今天减去年份,这样我们只 从年份中获得额外的月份,然后找到差异 从出生之日起几个月。这里“years”为变量,“year”为区间类型。

      3. days: 在这里我们减去年和月 已经从今天开始计算这是当前日期然后找到 出生后天数的差异。其中“months”为变量,“month”为区间类型。

      如果需要,您可以使用 datetime 代替 date 作为参数,也可以根据需要格式化返回值。

      【讨论】:

        【解决方案3】:
        SELECT *, YEAR(CURDATE()) - YEAR(birthdate) AS age FROM user;
        

        我从下面的文章中找到了一些有用的查询来计算年龄:- http://www.gizmola.com/blog/archives/archives/107-Calculate-a-persons-age-in-a-MySQL-query.html

        【讨论】:

        • 这有问题。让我解释一下,如果我的生日是 1990 年 9 月,那么这个查询将在 2020 年 8 月 1 日返回 30,就像它在 2020 年 10 月 1 日一样。但是仔细想想,8 月份我还是 29 岁,而 10 月份我是 30 岁。
        【解决方案4】:
        DATE_FORMAT(FROM_DAYS(DATEDIFF(CURDATE(),'1869-10-02')), '%Y')+0 AS age;
        

        以上 MySQL 查询已经过测试和验证。它会给你准确的年龄。我从 Marcos 的回答中汲取了这个想法并切换了 DATEDIFF() 参数。

        【讨论】:

          【解决方案5】:
          DELIMITER $$ DROP FUNCTION IF EXISTS `test`.`__AGE` $$
              CREATE FUNCTION `_AGE`(in_dob datetime) RETURNS VARCHAR(100)
                  NO SQL
              BEGIN
                 DECLARE l_age VARCHAR(100);
                 DECLARE YEARS INT(11);
                 DECLARE MONTHS INT(11);
                 DECLARE DAYS INT(11);
                 DECLARE DIFFS FLOAT;
          
          
                 SET DIFFS=DATEDIFF(CURRENT_DATE(),in_dob) /365.25;
                 SET YEARS=FLOOR(DIFFS) ;
                 SET MONTHS=FLOOR((DIFFS - YEARS)*365.25/30.4375) MOD 12;
                 SET DIFFS=((DIFFS - YEARS)*365.25/30.4375);
                 SET DAYS=CEIL(((DIFFS-MONTHS)*30.4375)) MOD 31;
                 RETURN(CONCAT(YEARS, " Year ",MONTHS," Month ",DAYS," Days"));
          
              END $$
          DELIMITER ;
          
          SELECT __Age(CAST('1980-07-16' AS DATE));
          

          【讨论】:

          • 欢迎来到 SO Ravi Shankar。无论此解决方案是否有效,最好为您的查询添加描述。这样,OP 和其他阅读本文的人都会更好地了解您想要实现的目标。
          【解决方案6】:

          下面的 sql 对我来说很好用。始终使用CURRENT_DATE 和 dob 来计算实际年龄。

          SELECT 
              DATE_FORMAT(
                  FROM_DAYS(
                      DATEDIFF(CURRENT_DATE, dob)
                  ),
                  '%y Years %m Months %d Days'
              ) AS age 
          FROM 
              users
          

          【讨论】:

            【解决方案7】:

            假设给定日期大于当前日期,

            1.查找当前日期和给定日期的总天数。

            ->DATEDIFF(NOW(),'1988-05-01')

            2.从计算的天数中找出年数。

            ->DATEDIFF(NOW(),'1988-05-01')/365.25

            3.年龄应该是一个人填写的年数。为了得到它,我们可以使用 'floor' 来计算年数。

            ->FLOOR(DATEDIFF(NOW(),'1988-05-01')/365.25)

            示例:SELECT FLOOR(DATEDIFF(NOW(),'1988-05-01')/365.25) AS age;

            【讨论】:

            • 恭喜,您刚刚复制了接受的答案,投票最多的答案解释了错误的原因。
            • 请不要简单地发布代码。提供有关您的代码的一些解释或信息或用法。例如,请参阅this answer
            【解决方案8】:
            DELIMITER $$ DROP FUNCTION IF EXISTS `test`.`_AGE` $$
                CREATE FUNCTION `_AGE`(in_dob datetime) RETURNS VARCHAR(100)
                    NO SQL
                BEGIN
                   DECLARE l_age VARCHAR(100);
                   DECLARE YEARS INT(11);
                   DECLARE MONTHS INT(11);
                   DECLARE DAYS INT(11);
                   DECLARE DIFFS FLOAT;
            
            
                   SET DIFFS=DATEDIFF(CURRENT_DATE(),in_dob) /365.25;
                   SET YEARS=FLOOR(DIFFS) ;
                   SET MONTHS=FLOOR((DIFFS - YEARS)*365.25/30.4375) MOD 12;
                   SET DIFFS=((DIFFS - YEARS)*365.25/30.4375);
                   SET DAYS=CEIL(((DIFFS-MONTHS)*30.4375)) MOD 31;
                   SET l_age=CONCAT(YEARS, " Year ",MONTHS," Month ",DAYS," Days");
                   RETURN(l_age);
                END $$
            DELIMITER ;
            
            SELECT _Age(CAST('1980-07-16' AS DATE));
            

            【讨论】:

            • 为什么你的解决方案比旧的投票最多的答案更好?
            • 谢谢,这让我了解了如何在我的应用程序中使用年龄函数。
            【解决方案9】:

            取决于您的需求 - 提供 int 和 float 函数。
            - 您的业务规则可能会有所不同,因此请相应调整

            DROP FUNCTION IF EXISTS `age`; 
            CREATE FUNCTION `age` (
              `pdate_begin` DATE,
              `pdate_end` DATETIME
            ) RETURNS INT(11) UNSIGNED   
            COMMENT 'Calc age between two dates as INT' 
            DETERMINISTIC NO SQL SQL SECURITY DEFINER
            RETURN floor(datediff(pdate_end, pdate_begin) / 365.25) ;
            
            DROP FUNCTION IF EXISTS `age_strict`; 
            CREATE FUNCTION `age_strict` (
              `pdate_begin` DATE,
              `pdate_end` DATETIME
            ) RETURNS decimal(10,4)
            COMMENT 'Calc age between two dates as DECIMAL .4' 
            DETERMINISTIC NO SQL SQL SECURITY DEFINER
            RETURN round(datediff(pdate_end, pdate_begin) / 365.25, 4) ;
            
            -- test harness
            select 
                age(dob, now())        as age_int,
                age_strict(dob, now()) as age_dec
                from customer 
                where dob is not null 
                order by age(dob,now()) desc;
            
            -- test results
            dob,                  age_int,            age_dec
            1981-01-01 00:00:00        33             33.9713
            1987-01-09 00:00:00        27             27.9507
            2014-11-25 00:00:00         0              0.0739
            

            【讨论】:

              【解决方案10】:

              推荐使用Mysql:

              TIMESTAMPDIFF(YEAR, dob, CURDATE()) AS age;
              

              在查询中的用法:

              SELECT name, dob, TIMESTAMPDIFF(YEAR, dob, CURDATE()) AS age FROM pet;
              

              参考:http://dev.mysql.com/doc/refman/5.0/en/date-calculations.html

              【讨论】:

              • @Roy 我没有看到这个问题:select TIMESTAMPDIFF(YEAR, '2000-12-25', '2001-12-24'); // 0 vs select TIMESTAMPDIFF(YEAR, '2000-12-25', '2001-12-25'); // 1 这是迄今为止最干净的答案。
              【解决方案11】:

              这是迄今为止我能想到的最简单的方法:

              SELECT FLOOR(ABS(DATEDIFF(d, CURRENT_TIMESTAMP, dob))/365.25) AS age
              

              首先我们以天为单位获取日期差异,然后将其转换为年,然后 FLOOR 截断为数字的整数部分。

              【讨论】:

                【解决方案12】:

                Bryan Denny 的答案比公认的答案更正确(我不知道如何把它放在新答案以外的地方;这是我第一次使用 StackOverflow)。

                马科斯的第一次尝试:

                select DATEDIFF(customer.dob, '2010-01-01') / 365.25 as age
                

                首先会产生否定结果(DATEDIFF 的参数顺序错误),其次会在某些日期产生不准确的结果,例如:

                SELECT DATEDIFF('2010-05-11','1984-05-11') / 365.25 AS age
                

                产生结果:

                25.9986
                

                您不能总是简单地四舍五入,因为这也会导致其他输入的结果不准确。

                马科斯的第二次尝试:

                SELECT DATE_FORMAT(FROM_DAYS(DATEDIFF(customer.dob,'2010-01-01')), ‘%Y’)+0 AS age
                

                同样,参数的顺序是错误的,除了这次不是只产生一个负数,FROM_DAYS() 函数在负输入时不能正常工作。其次,如果我们仔细观察 FROM_DAYS() 函数的输出:

                select from_days(datediff('2010-09-16','1984-05-11'));
                

                上面的结果是:

                0026-05-08
                

                字面意思是“26 年 5 月 8 日(0 之后)”。请记住,对于日期时间类型,没有月份“0”,因此如果您想使用这种格式来测量包含月份的日期间隔,您必须从月份中减去 1。同样,对于日期组件,没有“0”,因此当日期恰好是生日时,结果不是您对此问题的预期:

                select from_days(datediff('2010-05-11','1984-05-11'));
                

                产生:

                0025-12-31
                

                如果我们使用 Marcos 的日期格式缩短它会给我们“25”,这是对年龄的错误计算。

                Bryan Denny 的回答在所有这些极端情况下都是正确的。他的公式很巧妙:

                SELECT DATE_FORMAT(reference, '%Y') - DATE_FORMAT(birthdate, '%Y') - (DATE_FORMAT(reference, '00-%m-%d') < DATE_FORMAT(birthdate, '00-%m-%d')) AS age
                

                第一部分计算两个日期之间的年差。所以如果我们分别以“2010”和“1984”作为参考和生日,结果是“26”。然后第二部分基本上计算“生日月份和日期是否出现在参考月份和日期之后?”如果是这样,它“还没有发生”,所以我们需要从年份差异中减去额外的 1 来弥补这一点。这由

                所以,完整的例子:

                1)

                Reference date: 2010-05-10;
                Birthdate: 1984-05-11
                
                Year difference = 2010 - 1984 = 26
                Month and day comparison: May 10th < May 11th? Yes => subtract an additional year
                Calculated age: 25 years
                

                2)

                Reference date: 2010-05-11;
                Birthdate: 1984-05-11
                
                Year difference = 2010 - 1984 = 26
                Month and day comparison: May 11th < May 11th? No => subtract 0
                Calculated age: 26 years
                

                我希望这能让人们更清楚地了解情况!

                【讨论】:

                • 最快的查询是@almaruf 提供的
                【解决方案13】:

                几种方法:

                select DATEDIFF(customer.dob, '2010-01-01') / 365.25 as age
                
                SELECT DATE_FORMAT(FROM_DAYS(DATEDIFF(customer.dob,'2010-01-01')), ‘%Y’)+0 AS age
                

                希望对你有帮助

                【讨论】:

                • 很高兴它对您有所帮助。请将答案标记为已接受,以便其他人将来可以使用它:-)
                • 我很好奇:0.25 是干什么用的?
                • 从技术上讲,它是 365.2425,因为能被 100 整除的年份不是闰年,除非它们也能被 400 整除。
                • 我相信第二种解决方案将 customer.dob 和 NOW() 混淆了。它应该是.. SELECT DATE_FORMAT(FROM_DAYS(DATEDIFF('2010-01-01', customer.dob)), '%Y')+0 AS age
                • 更简单:TIMESTAMPDIFF(YEAR,dob,CURDATE()) AS age #use dob in Y-m-d mysql format
                【解决方案14】:
                SELECT DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(dob, '%Y') - (DATE_FORMAT(NOW(), '00-%m-%d') < DATE_FORMAT(dob, '00-%m-%d')) AS age
                

                【讨论】:

                • 这个比公认的答案好。感谢发帖!
                • 谢谢。我会使用 year(x) 而不是 date_format(x, '%Y') 否则很好。
                • 我们已经有了日期,不必将它们转换为字符串然后再转换回整数。只需使用TIMESTAMPDIFF(YEAR, dob, CURDATE())
                • 这甚至不正确,当一年中的日期在生日之前时,TIMESTAMPDIFF 可以正常工作。这个答案四舍五入。
                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2023-02-15
                • 1970-01-01
                • 2011-02-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多