2010-06-10 2 views
17

Desidero calcolare l'età corrente dalla data di nascita nella mia funzione Oracle.Calcolo dell'età Oracle dalla data di nascita e oggi

Quello che sto usando è (Today-Dob)/30/12, ma questo non è accurato poiché alcuni mesi hanno 31 giorni.

Ho bisogno di ottenere l'età corretta con la massima precisione. Come lo posso fare?

+0

un'occhiata a questo post, penso che abbia quello che vi serve: http://stackoverflow.com/questions/43819/oracle -equivalent-to-sql-server-sybase-datediff – Jay

+1

Solo alcuni commenti pedanti. Quando diciamo "età" è probabilmente una buona idea riflettere più attentamente su cosa significhi la parola * *. Normalmente, quando qualcuno dice "età", in realtà * significa "* quanti anniversari hanno superato *". Scientificamente, se esprimiamo l'età di due persone in anni, non possiamo confrontarli perfettamente, indipendentemente dalla precisione, perché la loro * età effettiva * sarà diversa a seconda di quando sono nati - ad es. erano nati in un anno bisestile; quanti secondi bisestili sono stati aggiunti/sottratti da allora; erano nati prima del settembre 1752? (1/2) –

+0

(2/2) Dipende da cosa è effettivamente la domanda - cioè "quale di queste due persone ha vissuto più a lungo" dovrebbe essere risposto usando un'unità di tempo che non cambia in modo significativo (ad esempio giorni, o secondi). "Questa persona ha passato il suo diciottesimo compleanno" è una domanda diversa, che direi più vicina a ciò che la maggior parte della gente intende per "età". –

risposta

33
SQL> select trunc(months_between(sysdate,dob)/12) year, 
    2   trunc(mod(months_between(sysdate,dob),12)) month, 
    3   trunc(sysdate-add_months(dob,trunc(months_between(sysdate,dob)/12)*12+trunc(mod(months_between(sysdate,dob),12)))) day 
    4 from (Select to_date('15122000','DDMMYYYY') dob from dual); 

     YEAR  MONTH  DAY 
---------- ---------- ---------- 
     9   5   26 

SQL> 
2

e un'alternativa senza utilizzare alcun aritmetica e numeri (anche se non c'è niente di sbagliato in questo):

SQL> with some_birthdays as 
    2 (select date '1968-06-09' d from dual union all 
    3 select date '1970-06-10' from dual union all 
    4 select date '1972-06-11' from dual union all 
    5 select date '1974-12-11' from dual union all 
    6 select date '1976-09-17' from dual 
    7 ) 
    8 select trunc(sysdate) today 
    9  , d birth_date 
10  , extract(year from numtoyminterval(months_between(trunc(sysdate),d),'month')) age 
11 from some_birthdays 
12/

TODAY    BIRTH_DATE     AGE 
------------------- ------------------- ---------- 
10-06-2010 00:00:00 09-06-1968 00:00:00   42 
10-06-2010 00:00:00 10-06-1970 00:00:00   40 
10-06-2010 00:00:00 11-06-1972 00:00:00   37 
10-06-2010 00:00:00 11-12-1974 00:00:00   35 
10-06-2010 00:00:00 17-09-1976 00:00:00   33 

5 rows selected. 
13

Per la logica di business di solito trovo un numero decimale (in anni) è utile:

select months_between(TRUNC(sysdate), 
         to_date('15-Dec-2000','DD-MON-YYYY') 
        )/12 
as age from dual; 

     AGE 
---------- 
9.48924731 
+0

AskTOM (Connor McDonald) dice che fallisce in pochissimi casi: https://asktom.oracle.com/pls/apex/f? p = 100: 11 ::: NO: RP: P11_QUESTION_ID: 9531934000346471628 Raccomanda questo: trunc ((to_number (to_char (ora, 'YYYYMMDD')) - to_number (to_char (birth, 'YYYYMMDD ')))/10000) –

+0

Ciao @ RaúlMoreno, quella semplice formula in realtà si traduce in una precisione molto inferiore. Questo articolo riguarda il calcolo dell'età solo negli interi. Lo stesso Connor dice "Questa è un'approssimazione ragionevole, ma comunque ... un'approssimazione". Il mio algoritmo è molto più accurato e non soffre del problema originale espresso in quel collegamento (il numero di giorni per 365 sarà spesso errato, per ovvie ragioni ovvi). –

+0

Oh! scusa, non ho notato che voleva i decimali. Volevo l'età, reale, negli anni, tenendo conto degli anni bisestili, ecc.e questo è l'unico che sembra sempre farlo bene (e non è quello che divide per 365). –

2

O che ne dici di questo?

with some_birthdays as 
( 
    select date '1968-06-09' d from dual union all 
    select date '1970-06-10' from dual union all 
    select date '1972-06-11' from dual union all 
    select date '1974-12-11' from dual union all 
    select date '1976-09-17' from dual 
) 
select trunc(sysdate) today 
, d birth_date 
, floor(months_between(trunc(sysdate),d)/12) age 
from some_birthdays; 
2

Questo sembra molto più facile di quello che qualcun altro ha suggerito

select sysdate-to_date('30-jul-1977') from dual; 
+0

Questo non è corretto in quanto è implicitamente la conversione di una stringa in una data, che potrebbe andare terribilmente male. – Ben

-3

select (SYSDATE-DOB)/365 "Age" dalla doppia

2
SELECT 
TRUNC((SYSDATE - TO_DATE(DOB, 'YYYY-MM-DD'))/ 365.25) AS AGE_TODAY FROM DUAL; 

Questo è facile e dritto al il punto.

1

Età (anni pieni) della persona:

SELECT 
    TRUNC(months_between(sysdate, per.DATE_OF_BIRTH)/12) AS "Age" 
FROM PD_PERSONS per 
0
SQL>select to_char(to_date('19-11-2017','dd-mm-yyyy'),'yyyy') - to_char(to_date('10-07-1986','dd-mm-yyyy'),'yyyy') year, 
to_char(to_date('19-11-2017','dd-mm-yyyy'),'mm') - to_char(to_date('10-07-1986','dd-mm-yyyy'),'mm') month, 
to_char(to_date('19-11-2017','dd-mm-yyyy'),'dd') - to_char(to_date('10-07-1986','dd-mm-yyyy'),'dd') day from dual; 

     YEAR  MONTH  DAY 
---------- ---------- ---------- 
     31   4   9