2010-03-28 12 views

Odpowiedz

26

kilka sposobów:

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 

Nadzieja to pomaga

+0

to jest doskonałe! wielkie dzięki! –

+0

Cieszę się, że ci pomogło. Proszę oznaczyć odpowiedź jako zaakceptowaną, aby inni mogli z niej korzystać w przyszłości :-) –

+0

Jestem ciekawy: po co jest 0,25? – 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

Ten jest lepszy niż zaakceptowana odpowiedź. Dzięki za publikację! –

+1

Dzięki. Używałbym 'year (x)' zamiast 'date_format (x, '% Y'), w przeciwnym razie jest wspaniale. – Tobia

19

odpowiedź Bryan Denny jest bardziej poprawna niż zaakceptowanej odpowiedzi (nie był pewien, jak umieścić to w innym miejscu niż nowa odpowiedź, to jest mój pierwszy raz na StackOverflow).

Marcos' pierwsza próba:

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

będzie najpierw uzyskując wynik negatywny (argumenty do DateDiff są w złej kolejności), a po drugie będzie produkować niedokładne wyniki dla niektórych terminach, np:

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

daje wynik:

25.9986 

nie po prostu można zawsze zaokrąglić, ponieważ spowoduje to również niedokładne wyniki dla innych danych wejściowych.

Marcos' Druga próba:

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

Znowu, argumenty są w niewłaściwej kolejności, ale tym razem zamiast po prostu tworząc liczbę ujemną, FROM_DAYS() funkcja nie działa poprawnie z wejściem ujemnym. Po drugie, jeśli przyjrzymy się bliżej wyjścia z FROM_DAYS() Funkcja:

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

Rezultatem powyższego jest:

0026-05-08 

która jest dosłownie „8 maja, Rok 26 (po 0) ". Pamiętaj, że w przypadku typów datetime nie ma miesiąca "0", więc jeśli chcesz użyć tego formatu do mierzenia przedziału czasu zawierającego miesiące, musisz odjąć 1 od miesiąca. Podobnie ze składnikiem dzień, nie ma „0”, więc wynik nie jest to, czego można spodziewać się tego problemu, gdy dzieje się data urodzin:

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

produkuje:

0025-12-31 

co jeśli skracamy używając formatowania daty Marcos daje nam "25", co jest nieprawidłową kalkulacją wieku.

Odpowiedź Bryana Denny jest poprawna we wszystkich tych skrajnych przypadkach. Jego formuła jest sprytna:

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

Pierwsza część oblicza różnicę w latach między tymi dwoma datami. Jeśli więc weźmiemy odpowiednio "2010" i "1984" jako odniesienia i datę urodzenia, wynikiem jest "26". W drugiej części oblicza się w istocie "Czy miesiąc i dzień z datą urodzenia występują po miesiącu i dniu odniesienia?" Jeśli tak, to "jeszcze się nie wydarzyło", więc musimy odjąć dodatkową 1 od różnicy roku, aby to zrekompensować. Jest to uwzględnione w wyniku porównania <, które zwraca 1, jeśli jest prawdziwe, a 0, jeśli jest fałszywe.

Tak, pełne przykładów:

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 

Mam nadzieję, że to sprawia, że ​​rzeczy bardziej zrozumiałe dla ludzi!

+1

najszybszym zapytaniem jest to, co @almaruf dostarczył – user1016265

-2

Jest to najprostszy mogę wymyślić do tej pory:

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

Najpierw otrzymujemy różnicę dat w dni, a następnie przekształcić go lat, a następnie obcina FLOOR do części całkowitej liczby.

2

Poniższy sql działa dobrze dla mnie. Zawsze używaj CURRENT_DATE z opcją dob, aby obliczyć rzeczywisty wiek.

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

Przyjęto podana data jest większa niż bieżąca,

1.Find łączna liczba dni/b bieżącej daty i dany dzień.

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

2.Find no lat od dni nie oblicza.

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

3. wiek nie powinien być od lat przeprowadzać osoby. Aby to uzyskać, możemy użyć "podłogi" do obliczonej liczby lat.

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

przykład: SELECT FLOOR(DATEDIFF(NOW(),'1988-05-01')/365.25) AS age;

+0

Gratulacje, właśnie skopiowałeś zaakceptowaną odpowiedź, która została wybrana jako pierwsza odpowiedź wyjaśnia, dlaczego jest źle. –

+0

Proszę nie po prostu pisać kodu. Podaj wyjaśnienia lub informacje na temat Twojego kodu lub użycia. Na przykład zobacz [ta odpowiedź] (http://stackoverflow.com/a/16893057/756941). – NAZIK

+0

Dzięki za właściwy kierunek. –

0

W zależności od potrzeb - dostępne funkcje int i float.
- Twoje reguły biznesowe mogą się różnić więc dostosować odpowiednio

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

Dlaczego Twoje rozwiązanie jest lepsze niż starsze najczęściej wybierane odpowiedzi? – Marki555

+0

Dzięki, dałem mi pomysł, jak uzyskać funkcję wiekową, działającą w mojej aplikacji. –

-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

Witamy w SO Ravi Shankar. Bez względu na to, czy to rozwiązanie działa, lepiej byłoby dodać opis zapytań. W ten sposób OP i każdy, kto to czyta, będzie lepiej rozumieć, co chcesz osiągnąć. – dhh

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

Przede zapytania MySQL zostało przetestowane i sprawdzone. Daje ci dokładny wiek w latach. Wziąłem ten pomysł z odpowiedzi Marcosa i zmieniłem parametry DATEDIFF().

Powiązane problemy