2010-03-28 36 views
24

Tôi cần tính tuổi của "khách hàng" kể từ ngày sinh của họ.Cách lấy tuổi từ trường D.O.B trong MySQL?

Tôi đã cố gắng sử dụng như sau:

DATEDIFF (năm, customer.dob, "2010/01/01");

Nhưng có vẻ như nó không hoạt động.

Bất kỳ ý tưởng nào? Tôi BIẾT nó sẽ là một cái gì đó đơn giản!

Cảm ơn

Trả lời

26

Một vài cách sau:

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 

Hy vọng điều này sẽ giúp bạn

+0

thats tuyệt vời! cảm ơn rất nhiều! –

+0

Vui vì nó đã giúp bạn. Vui lòng đánh dấu câu trả lời là được chấp nhận, vì vậy những người khác có thể sử dụng câu trả lời trong tương lai :-) –

+0

Tôi tò mò: 0.25 là gì? – ryanprayogo

45
SELECT DATE_FORMAT(NOW(), '%Y') - DATE_FORMAT(dob, '%Y') - (DATE_FORMAT(NOW(), '00-%m-%d') < DATE_FORMAT(dob, '00-%m-%d')) AS age 
+2

Cái này tốt hơn câu trả lời được chấp nhận. Cảm ơn vì đăng! –

+1

Cảm ơn. Tôi sẽ sử dụng 'year (x)' thay vì 'date_format (x, '% Y')' nếu không thì nó rất tuyệt. – Tobia

19

câu trả lời Bryan Denny là hơn đúng hơn là câu trả lời chấp nhận (Tôi đã không chắc chắn như thế nào để đặt điều này ở một nơi khác ngoài câu trả lời mới, đây là lần đầu tiên tôi sử dụng StackOverflow).

Marcos' nỗ lực đầu tiên:

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

trước hết sẽ mang lại một kết quả tiêu cực (các đối số DATEDIFF là theo thứ tự sai), và thứ hai sẽ tạo ra kết quả không chính xác đối với một số ngày, ví dụ:

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

tạo ra kết quả:

25.9986 

Bạn không thể chỉ đơn giản là luôn làm tròn lên, bởi vì điều đó cũng sẽ gây ra kết quả không chính xác cho các đầu vào khác. nỗ lực thứ hai

Marcos':

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

Một lần nữa, các đối số theo thứ tự sai, ngoại trừ thời gian này thay vì chỉ sản xuất một số âm, FROM_DAYS() chức năng không hoạt động đúng với đầu vào tiêu cực. Thứ hai, nếu chúng ta nhìn sâu hơn về đầu ra của FROM_DAYS() chức năng:

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

Kết quả trên là:

0026-05-08 

mà nghĩa đen là "ngày 08 tháng 5, năm 26 (sau 0) ". Hãy nhớ rằng đối với các loại ngày giờ, không có tháng "0", vì vậy nếu bạn muốn sử dụng định dạng này để đo khoảng thời gian có tháng bao gồm, bạn phải trừ 1 từ tháng. Tương tự, với các thành phần ngày, không có "0", do đó kết quả không phải là điều bạn mong muốn cho vấn đề này khi ngày sẽ xảy ra là sinh nhật:

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

sản xuất:

0025-12-31 

nếu chúng ta rút ngắn bằng cách sử dụng định dạng ngày Marcos 'sẽ cho chúng ta "25", đây là cách tính tuổi không chính xác.

Câu trả lời của Bryan Denny là chính xác trong tất cả các trường hợp cạnh này. Công thức của anh ta khá thông minh:

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

Phần đầu tiên tính chênh lệch năm giữa hai ngày. Vì vậy, nếu chúng ta lấy "2010" và "1984" làm tham chiếu và ngày sinh tương ứng, kết quả là "26". Phần thứ hai sau đó tính toán về cơ bản "Tháng và ngày sinh có xảy ra sau tháng và ngày tham chiếu không?" Nếu có, nó "chưa xảy ra", vì vậy chúng ta cần trừ một số 1 từ sự khác biệt trong năm để bù đắp cho điều này. Điều này được xử lý bởi kết quả của so sánh <, trả về 1 nếu đúng và 0 nếu sai.

Vì vậy, đầy đủ ví dụ:

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 

Tôi hy vọng điều này làm cho mọi thứ rõ ràng hơn cho mọi người!

+1

truy vấn nhanh nhất là những gì @almaruf cung cấp – user1016265

-2

này là đơn giản nhất tôi có thể đưa ra cho đến nay:

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

Đầu tiên chúng tôi nhận được sự khác biệt ngày trong ngày, sau đó chuyển nó sang năm, sau đó SÀN truncates đến phần nguyên của số.

2

Hình dưới đây hoạt động tốt cho tôi. Luôn sử dụng CURRENT_DATE với dob để tính tuổi thực tế.

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

Giả ngày nhất định là lớn hơn ngày hiện tại,

1.Find tổng không có ngày b/w ngày hiện tại và ngày cụ thể.

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

2. Tìm các không của năm, kể từ tính không có ngày.

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

3.The tuổi nên đã hoàn thành không của năm bởi một người. Để có được nó, chúng ta có thể sử dụng 'sàn' để tính số năm.

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

Ví dụ: SELECT FLOOR(DATEDIFF(NOW(),'1988-05-01')/365.25) AS age;

+0

Xin chúc mừng, bạn vừa nhân đôi câu trả lời được chấp nhận, được bình chọn hàng đầu câu trả lời giải thích tại sao sai. –

+0

Vui lòng không chỉ cần đăng mã. Cung cấp một số lời giải thích hoặc thông tin hoặc cách sử dụng về mã của bạn. Ví dụ: xem [câu trả lời này] (http://stackoverflow.com/a/16893057/756941). – NAZIK

+0

Cảm ơn bạn đã đi đúng hướng. –

21

Sử dụng Mysql đề nghị:

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

Cách sử dụng trong một truy vấn:

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

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

+0

Điều này không chính xác khi sinh nhật diễn ra vào ngày đó, do đó bạn nên thêm 1 vào ngày hiện tại. – user114111121

0

Phụ thuộc vào nhu cầu của bạn - chức năng int và float được cung cấp.
- quy tắc kinh doanh của bạn có thể khác nhau nên điều chỉnh cho phù

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 
1
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)); 
+0

Tại sao giải pháp của bạn tốt hơn các câu trả lời được bình chọn nhiều nhất? – Marki555

+0

Cảm ơn, điều này đã cho tôi một ý tưởng về cách để có được một chức năng tuổi tác làm việc trong ứng dụng của tôi. –

-1
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)); 
+0

Chào mừng bạn đến với SO Ravi Shankar. Bất kể thời gian giải pháp này đang hoạt động, Sẽ tốt hơn nếu bạn thêm mô tả cho các truy vấn của mình. Bằng cách đó, OP và bất kỳ ai khác đọc sách này sẽ hiểu rõ hơn về những gì bạn muốn đạt được. – dhh

0
DATE_FORMAT(FROM_DAYS(DATEDIFF(CURDATE(),'1869-10-02')), '%Y')+0 AS age; 

Trên truy vấn MySQL đã được thử nghiệm và xác minh. Nó sẽ cho bạn tuổi chính xác trong nhiều năm. Tôi đã lấy ý tưởng này từ câu trả lời của Marcos và chuyển các tham số DATEDIFF().

Các vấn đề liên quan