Calculate age in MySQL (InnoDB) - mysql

If I have a person's date of birth stored in a table in the form dd-mm-yyyy, and I subtract it from the current date, what format is the date returned in?
How can I use this returned format to calculate someone's age?

You can use TIMESTAMPDIFF(unit, datetime_expr1, datetime_expr2) function:
SELECT TIMESTAMPDIFF(YEAR, '1970-02-01', CURDATE()) AS age
Demo

If the value is stored as a DATETIME data type:
SELECT YEAR(CURRENT_TIMESTAMP) - YEAR(dob) - (RIGHT(CURRENT_TIMESTAMP, 5) < RIGHT(dob, 5)) as age
FROM YOUR_TABLE
Less precise when you consider leap years:
SELECT DATEDIFF(CURRENT_DATE, STR_TO_DATE(t.birthday, '%d-%m-%Y'))/365 AS ageInYears
FROM YOUR_TABLE t

SELECT TIMESTAMPDIFF (YEAR, YOUR_COLUMN, CURDATE()) FROM YOUR_TABLE AS AGE
Check the demo image below
Simple but elegant..

Use:
select *,year(curdate())-year(dob) - (right(curdate(),5) < right(dob,5)) as age from your_table
In this way, you consider even month and day of birth in order to have a more accurate age calculation.

select floor(datediff (now(), birthday)/365) as age

Simply:
DATE_FORMAT(FROM_DAYS(TO_DAYS(NOW())-TO_DAYS(`birthDate`)), '%Y')+0 AS age

Since the question is being tagged for mysql, I have the following implementation that works for me and I hope similar alternatives would be there for other RDBMS's. Here's the sql:
select YEAR(now()) - YEAR(dob) - ( DAYOFYEAR(now()) < DAYOFYEAR(dob) ) as age
from table
where ...

Try this:
SET #birthday = CAST('1980-05-01' AS DATE);
SET #today = CURRENT_DATE();
SELECT YEAR(#today) - YEAR(#birthday) -
(CASE WHEN
MONTH(#birthday) > MONTH(#today) OR
(MONTH(#birthday) = MONTH(#today) AND DAY(#birthday) > DAY(#today))
THEN 1
ELSE 0
END);
It returns this year - birth year (how old the person will be this year after the birthday) and adjusts based on whether the person has had the birthday yet this year.
It doesn't suffer from the rounding errors of other methods presented here.
Freely adapted from here

Simply do
SELECT birthdate, (YEAR(CURDATE())-YEAR(birthdate)) AS age FROM `member`
birthdate is field name that keep birthdate name
take CURDATE() turn to year by YEAR() command
minus with YEAR() from the birthdate field

This is how to calculate the age in MySQL:
select
date_format(now(), '%Y') - date_format(date_of_birth, '%Y') -
(date_format(now(), '00-%m-%d') < date_format(date_of_birth, '00-%m-%d'))
as age from table

You can make a function to do it:
drop function if exists getIdade;
delimiter |
create function getIdade( data_nascimento datetime )
returns int
begin
declare idade int;
declare ano_atual int;
declare mes_atual int;
declare dia_atual int;
declare ano int;
declare mes int;
declare dia int;
set ano_atual = year(curdate());
set mes_atual = month( curdate());
set dia_atual = day( curdate());
set ano = year( data_nascimento );
set mes = month( data_nascimento );
set dia = day( data_nascimento );
set idade = ano_atual - ano;
if( mes > mes_atual ) then
set idade = idade - 1;
end if;
if( mes = mes_atual and dia > dia_atual ) then
set idade = idade - 1;
end if;
return idade;
end|
delimiter ;
Now, you can get the age from a date:
select getIdade('1983-09-16');
If you date is in format Y-m-d H:i:s, you can do this:
select getIdade(substring_index('1983-09-16 23:43:01', ' ', 1));
You can reuse this function anywhere ;)

I prefer use a function this way.
DELIMITER $$ DROP FUNCTION IF EXISTS `db`.`F_AGE` $$
CREATE FUNCTION `F_AGE`(in_dob datetime) RETURNS int(11)
NO SQL
BEGIN
DECLARE l_age INT;
IF DATE_FORMAT(NOW( ),'00-%m-%d') >= DATE_FORMAT(in_dob,'00-%m-%d') THEN
-- This person has had a birthday this year
SET l_age=DATE_FORMAT(NOW( ),'%Y')-DATE_FORMAT(in_dob,'%Y');
ELSE
-- Yet to have a birthday this year
SET l_age=DATE_FORMAT(NOW( ),'%Y')-DATE_FORMAT(in_dob,'%Y')-1;
END IF;
RETURN(l_age);
END $$
DELIMITER ;
now to use
SELECT F_AGE('1979-02-11') AS AGE;
OR
SELECT F_AGE(date) AS age FROM table;

There is two simple ways to do that:
 
select("users.birthdate",
DB::raw("FLOOR(DATEDIFF(CURRENT_DATE, STR_TO_DATE(users.birthdate, '%Y-%m-%d'))/365) AS age_way_one"),
 
select("users.birthdate",DB::raw("(YEAR(CURDATE())-YEAR(users.birthdate)) AS age_way_two"))

Related

Create a loop based on date Mysql

I have a query :
insert into fookoo_business
select stat_date, sum(spend), sum(revenue)
from hooloo_business;
that i want to run for each date from '2017-01-20' until yesterday (it means the query will run 434 times if we're at 01/04/2018), for each date separately
(in a loop).
how can i create a loop in Mysql to do it for me?
I have tried:
creating procedure for the query select #stat_date, sum(spend), sum(revenue)
I called 'query'
then :
CREATE PROCEDURE loop_procedure()
BEGIN
SET #stat_date='2018-03-20';
CALL 'query';
REPEAT
SET #stat_date = #stat_date + INTERVAL 1 DAY;
UNTIL #stat_date = CURDATE() END REPEAT;
END
eventually i've used the following logic within a stored procedure to fetch the data:
PROCEDURE `x_monitoring_loop`()
BEGIN
DECLARE i INT;
DECLARE len INT;
SET len = 434;
SET i = 0;
WHILE (i < len) DO
SET #stat_date= CURDATE()-INTERVAL 1 DAY;
SET #stat_date= #stat_date- INTERVAL i DAY;
Insert query;
SET i = i +1;
END WHILE;
This way the query ran 434 times for each day, beginning at current date - 1 day.
I do not know why you want to use a procedure,I think we can just use a query sql to do it:
INSERT INTO fookoo_business
SELECT stat_date, SUM(spend), SUM(revenue)
FROM hooloo_business
WHERE stat_date BETWEEN STR_TO_DATE('2017-01-02', '%Y-%m-%d') -- start date
AND DATE_SUB(NOW(), INTERVAL 1 DAY) -- end date
GROUP BY stat_date;

stored procedure returns wrong value

I have a stored procedure that keeps giving me wrong answer. I asked the procedure to return the value of motor insurance. I run the procedure and give me the total of motor insurance premium but if I run it for the 4th time it give me the ageRange select statement value.
I moved the code into a new procedure but still the same.
My code
DELIMITER $$
CREATE DEFINER=`root`#`localhost` PROCEDURE `cal_motor_qoute`(in
coverID int , in dob date,
in sumMotor double , out QMsg varchar(200))
BEGIN
declare policy_cover , total , insRatio, ageExtra double;
declare ageRange int;
declare price_list varchar(200);
SELECT DATEDIFF(NOW(),dob) / 365.25 AS ageRange from dual;
if (coverID = 1) then
set policy_cover = 0.002;
elseif (coverID = 2) then
set policy_cover = 0.0025;
elseif (coverID = 3) then
set policy_cover = 0.003;
elseif (coverID = 4) then
set policy_cover = 0.0035;
end if;
if ( ageRange < 25) then
set ageExtra = 0.0005;
else
set ageExtra = 0.000;
end if;
set insRatio = policy_cover + ageExtra;
set total = (sumMotor * insRatio )* 10;
set QMsg = concat('total Premium is: ',total);
select #QMsg;
END
Any help please..
SELECT DATEDIFF(NOW(),dob) / 365.25 AS ageRange from dual;
will not set the variable ageRange, but it will do a select (of the calculated value) and name the column of the resultset ageRange.
The (or rather: one) way to set the value of your variable is to use into:
SELECT DATEDIFF(NOW(),dob) / 365.25 into ageRange from dual;
Although this is probably not the most precise way to calculate the age of a person anyway. You might want to replace
if ( ageRange < 25) then
with
if ( dob > date_sub(now(), interval 25 year) ) then

Need to loop a MySql Query by changing a parameter

I am very new to mysql scripts , I want to execute this query by incrementing 00:00:00 time to 30 minutes .
something like this
Select count(*)
FROM ctrdb.CTR_LINE_ITEM
where LOAD_DATE BETWEEN '2016-05-18 00:00:00' AND '2016-05-18 00:30:00'
order by load_date;
Select count(*)
FROM ctrdb.CTR_LINE_ITEM
where LOAD_DATE BETWEEN '2016-05-18 00:30:00' AND '2016-05-18 00:60:00'
order by load_date;
Can you guys please help me ?
if you wan to achieve this in mysql and want to get separate resultset for each query
then you need to run your query in loop by using stored procedure.
read loop in mysql http://www.mysqltutorial.org/stored-procedures-loop.aspx
or there are not multiple queries then you can use union as well
DELIMITER $$
CREATE PROCEDURE getdata()
BEGIN
DECLARE x INT;
DECLARE maximum INT; # you can use date as well
DECLARE startdate DATE;
DECLARE enddate DATE;
SET x =0;
SET maximum = 10;
SET startdate = '2016-05-18 00:00:00';
loop_label: LOOP
IF x > 10 THEN
LEAVE loop_label;
END IF;
SET x = x + 1;
SET enddate = startdate + INTERVAL 30 MINUTE;
Select count(*) ,startdate
FROM ctrdb.CTR_LINE_ITEM
where LOAD_DATE BETWEEN '2016-05-18 00:00:00' AND '2016-05-18 00:30:00'
order by load_date;
SET startdate = startdate + INTERVAL 30 MINUTE;
END LOOP;
END $$
DELIMITER ;

Check Each Date In Date Range

In SQL Server 2008 I have a startdate and an enddate being passed to my procedure. I need to check each date in the range to see if it exists in my validworkday table. I have no clue where to begin on this, but this is how start/end day are set-up
Declare #startdate date, #enddate date
Set #startdate = '01/01/2015'
Set #enddate = '04/16/2015'
Now how can I iterate each date in this span to see if validworkday = true for it? The check I would need to run is like so (checking each date)
Select isvalidworkday
from validworkdays
where date = '01/01/2015'
Select isvalidworkday
from validworkdays
where date = '01/02/2015'
This is syntax that I found from #Incidently years ago (I don't remember where that original post is, but hopefully this will be enough to give the credit), that I still use today. All I did was slightly tweak his syntax to insert the data into a temp table and add a cursor to iterate each individual date.
DECLARE #DateFrom smalldatetime, #DateTo smalldatetime, #firstdate date;
SET #DateFrom='20000101';
SET #DateTo='20081231';
-------------------------------
WITH T(date)
AS
(
SELECT #DateFrom
UNION ALL
SELECT DateAdd(day,1,T.date)
FROM T
WHERE T.date < #DateTo
)
SELECT date
INTO #AllDates
FROM T OPTION (MAXRECURSION 32767);
Declare c1 Cursor For
Select date
FROM #AllDates
Open c1
Fetch Next From c1 Into #firstdate
While ##FETCH_STATUS = 0
Begin
--Do whatever processing you need here
Fetch Next From c1 Into #firstdate
End
Close c1
Deallocate c1
Code should only live in one place and not be rewritten. Create functions (once) like GetAllIntsBetween(), GetAllMonths(), GetAllDates(), etc. Then used them like:
DECLARE #startdate date = '01/01/2015', #enddate date = '04/16/2015'
SELECT allDates.TheDate,
isnull(v.isvalidworkday, false) AS isvalidworkday
FROM dbo.GetAllDates(#startdate, #enddate) AS allDates
LEFT JOIN validworkdays AS v
ON allDates.TheDate = v.MyDate
The GetAllDates() would be:
CREATE FUNCTION dbo.GetAllDates(#Start DATETIME, #End DATETIME)
RETURNS
#AllDates TABLE
(
TheDate DATETIME
)
AS
BEGIN
IF #Start > #End
BEGIN
DECLARE #Temp DATETIME
SET #Temp = #Start
SET #Start = #End
SET #End = #Temp
END
WHILE #Start <= #End
BEGIN
INSERT INTO #AllDates
VALUES(#Start)
SET #Start = DATEADD(DAY, 1, #Start)
END
RETURN
END
(note: can change DATETIME to DATE)

How to get an age from a D.O.B field in MySQL?

I need to calculate the age of a "customer" from their date of birth.
I have tried to use the following:
DATEDIFF(year, customer.dob, "2010-01-01");
But it does not seem to work.
Any ideas? I KNOW it is going to be something simple!
Thanks
SELECT DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(dob, '%Y') - (DATE_FORMAT(NOW(), '00-%m-%d') < DATE_FORMAT(dob, '00-%m-%d')) AS age
Use Mysql recommended :
TIMESTAMPDIFF(YEAR, dob, CURDATE()) AS age;
Usage in a query :
SELECT name, dob, TIMESTAMPDIFF(YEAR, dob, CURDATE()) AS age FROM pet;
Ref: http://dev.mysql.com/doc/refman/5.0/en/date-calculations.html
A few ways:
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
Hope this helps you
Bryan Denny's answer is more correct than the accepted answer (I wasn't sure how to put this in somewhere other than a new answer; this is my first time on StackOverflow).
Marcos' first attempt:
select DATEDIFF(customer.dob, '2010-01-01') / 365.25 as age
will firstly yield a negative result (the arguments to DATEDIFF are in the wrong order), and secondly will produce inaccurate results for some dates, e.g.:
SELECT DATEDIFF('2010-05-11','1984-05-11') / 365.25 AS age
produces the result:
25.9986
You can't just simply always round up, because that will also cause inaccurate results for other inputs.
Marcos' second attempt:
SELECT DATE_FORMAT(FROM_DAYS(DATEDIFF(customer.dob,'2010-01-01')), ‘%Y’)+0 AS age
Again, the arguments are in the wrong order, except this time instead of just producing a negative number, the FROM_DAYS() function does not work correctly with negative input. Secondly, if we look closer at the output of the FROM_DAYS() function:
select from_days(datediff('2010-09-16','1984-05-11'));
The result of the above is:
0026-05-08
which is literally "8th of May, Year 26 (after 0)". Keep in mind that for datetime types, there is no month "0", so if you wanted to use this format to measure a date interval with months included, you'd have to subtract 1 from the month. Similarly, with the day component, there is no "0", so the result is not what you'd expect for this problem when the date happens to be the birthday:
select from_days(datediff('2010-05-11','1984-05-11'));
produces:
0025-12-31
which if we shorten using Marcos' date formatting gives us "25", which is an incorrect calculation of age.
Bryan Denny's answer is correct in all these edge cases. His formula is quite clever:
SELECT DATE_FORMAT(reference, '%Y') - DATE_FORMAT(birthdate, '%Y') - (DATE_FORMAT(reference, '00-%m-%d') < DATE_FORMAT(birthdate, '00-%m-%d')) AS age
The first part calculates the difference in years between the two dates. So if we take "2010" and "1984" as reference and birthdate respectively, the result is "26". The second part then calculates essentially "Does the birthdate month and day occur after the reference month and day?" If it does, it "hasn't happened yet", so we need to subtract an additional 1 from the year difference to make up for this. This is taken care of by the result of the < comparison, which returns 1 if true and 0 if false.
So, full examples:
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
I hope this makes things clearer for people!
The below sql works fine for me. Always use CURRENT_DATE with dob to calculate the actual age .
SELECT
DATE_FORMAT(
FROM_DAYS(
DATEDIFF(CURRENT_DATE, dob)
),
'%y Years %m Months %d Days'
) AS age
FROM
users
The easy way:
timestampdiff( YEAR, birth_date, now() ) AS age
SELECT *, YEAR(CURDATE()) - YEAR(birthdate) AS age FROM user;
I found some useful queries from below article for calculating age :-
http://www.gizmola.com/blog/archives/archives/107-Calculate-a-persons-age-in-a-MySQL-query.html
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));
DATE_FORMAT(FROM_DAYS(DATEDIFF(CURDATE(),'1869-10-02')), '%Y')+0 AS age;
Above MySQL query has been tested and verified. It will give you exact age in years. I have taken this idea from Marcos answer and switched DATEDIFF() parameters.
If you want years, months and days like "26 years 4 months and 27 days" then following is the age function for you:
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;
We are calculating the age from current date so I set today to curdate().
Now we are getting our years, months and days as following.
years: We get the difference in years from today to date of birth.
months: First we subtract the years from the today so that we only
get months that are extra from the years and then find the difference in
months from date of birth. Here "years" is the variable and "year" is interval type.
days: And here we subtract years and months that we
have already calculated from today which is current date then find
the diff in days from birth. Here "months" is the variable and "month" is interval type.
You can use datetime instead of date as argument if you want also you can format the return values as you like.
DROP FUNCTION IF EXISTS FN_GetDuration;
CREATE FUNCTION `FN_GetDuration`(p_STARTDATE DATETIME, p_ENDDATE DATETIME) RETURNS varchar(200) CHARSET utf8
DETERMINISTIC
BEGIN
DECLARE v_DAYS INT;
DECLARE v_MONTHS INT;
DECLARE v_YEARS INT;
DECLARE v_BASEMONTH INT;
DECLARE v_TOTALDAYS INT;
DECLARE v_STYRMONTHDAYS INT;
DECLARE v_ENYRMONTHDAYS INT;
DECLARE v_STYRMONTHS INT;
DECLARE v_ENYRMONTHS INT;
DECLARE v_DATESTRING VARCHAR(50);
DECLARE v_FROMDATE DATETIME;
DECLARE v_TODATE DATETIME;
DECLARE v_ENDMONTH INT(10);
DECLARE v_STARTMONTH INT(10);
DECLARE v_TempValue Varchar(10);
DECLARE v_Year Varchar(2);
DECLARE v_Month Varchar(2);
DECLARE v_Day Varchar(2);
SET v_BASEMONTH = 12; SET v_DAYS = 0; SET v_MONTHS=0; SET v_YEARS=0;
IF p_STARTDATE <= p_ENDDATE
THEN
IF p_STARTDATE <> p_ENDDATE
THEN
SET v_TOTALDAYS = FN_TotalDaysOfMonth(p_STARTDATE);
SET v_STYRMONTHDAYS = v_TOTALDAYS - DAY(p_STARTDATE) + 1;
SET v_ENYRMONTHDAYS = DAY(p_ENDDATE);
SET v_DAYS = v_STYRMONTHDAYS + v_ENYRMONTHDAYS;
END IF;
IF p_STARTDATE = p_ENDDATE
THEN
SET v_DAYS = 1;
END IF;
IF v_DAYS > v_TOTALDAYS
THEN
SET v_MONTHS=1;
SET v_DAYS = v_DAYS-v_TOTALDAYS;
END IF;
IF YEAR(p_STARTDATE) <> YEAR(p_ENDDATE)
THEN
SET v_STYRMONTHS = v_BASEMONTH - MONTH(p_STARTDATE);
SET v_ENYRMONTHS = MONTH(p_ENDDATE)-1;
SET v_MONTHS = v_MONTHS + v_STYRMONTHS + v_ENYRMONTHS;
SET v_DATESTRING = CONCAT(((YEAR(p_STARTDATE))+1 ) , '-01-01 ');
SET v_FROMDATE = v_DATESTRING;
SET v_DATESTRING = CONCAT(((YEAR(p_ENDDATE))-1 ) , '-12-31 ');
SET v_TODATE = v_DATESTRING;
IF YEAR(v_TODATE)<> YEAR(v_FROMDATE)
THEN
SET v_YEARS = (YEAR(v_TODATE)- YEAR(v_FROMDATE))+1;
ELSE
SET v_YEARS = 1;
END IF;
IF v_MONTHS >= v_BASEMONTH
THEN
SET v_YEARS = v_YEARS + 1;
SET v_MONTHS = v_MONTHS - v_BASEMONTH;
END IF;
ELSE
SET v_ENDMONTH = MONTH(p_ENDDATE);
SET v_STARTMONTH = MONTH(p_STARTDATE);
IF p_STARTDATE <> p_ENDDATE
THEN
SET v_MONTHS = v_MONTHS + ((v_ENDMONTH - v_STARTMONTH)-1);
END IF;
END IF;
END IF;
IF v_YEARS<10 THEN
SET v_Year=CONCAT('0', v_YEARS);
ELSE
SET v_Year= v_YEARS;
END IF;
IF v_MONTHS<10 THEN
SET v_Month= CONCAT('0', v_MONTHS);
ELSE
SET v_Month= v_MONTHS;
END IF;
IF v_DAYS<10 THEN
SET v_Day= CONCAT('0',v_DAYS);
ELSE
SET v_Day= v_DAYS;
END IF;
SET v_TempValue = CONCAT(v_Year, '-', v_Month, '-', v_Day);
RETURN v_TempValue;
END;
This is the simplest I could come up with so far:
SELECT FLOOR(ABS(DATEDIFF(d, CURRENT_TIMESTAMP, dob))/365.25) AS age
First we get the date difference in days, then convert it to years, then FLOOR truncates to the integer part of the number.
Depends on your needs
- int and float functions provided.
- Your business rules may differ so adjust accordingly
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
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));
Assumed the given date is greater than the current date,
1.Find the total no of days b/w the current date and the given date.
-> DATEDIFF(NOW(),'1988-05-01')
2.Find the no of years from the calculated no of days.
-> DATEDIFF(NOW(),'1988-05-01')/365.25
3.The age should be the completed no of years by a person. To get it, we can use 'floor' to the calculated no of years.
-> FLOOR(DATEDIFF(NOW(),'1988-05-01')/365.25)
Example: SELECT FLOOR(DATEDIFF(NOW(),'1988-05-01')/365.25) AS age;