Calcolare età - 2

di il
9 risposte

Calcolare età - 2

In un altro post che discuteva come calcolare l'età a partire dalla data di nascita, avevo scritto che nel mio caso  (SQLExpress) uso una colonna calcolata che quindi risulta aggiornata sempre, con la formula seguente

(datediff(year, [Data di nascita], getdate())

Questa formula, anche se funziona, è non del tutto corretta, in quanto non tiene conto dei giorni intercorsi dalla data di nascita, ma solo l'anno, per cui ad esempio una persona nata il 10 Dicembre 1980 risulta avere 2023-1980= 43 anni invece della età corretta, 42.

Per risolvere il problema, scartabellando in rete, pareva che la soluzione fosse a portata di mano:

DATE_FORMAT(FROM_DAYS(DATEDIFF(NOW(), [date_of_birth])), '%Y') + 0;

spiegata così:

- datediff dà il numero di  giorni fra le due date

- from_days converte il numero di cui sopra in data

- date_format con ‘%Y’ dà il numero di anni nella forma 00xx

- sommiamo il risultato a 0 per eliminare gli zeri superflui

La formula però non funziona con sql server, ma sospetto (come dicevo sto imparando….)  che funzioni solo con MYSQL.

1) la sintassi di datediff è diversa: la data odierna appare prima di quella di nascita, e manca la keyword “year” (o "day")

2) NOW() in sql server non funziona, ci vuole getdate()

3) FROM_DAYS e DATE_FORMAT non vengono riconosciuti come funzione

Tutto questo noioso sproloquio per arrivare alla domanda: ma c'è l'equivalente Sql server di questa formula? Ho provato  a lungo, ma non sono riuscito a far accettare niente a sqlserver, particolarmente FROM_DAYS sembra non avere equivalente. Per il momento, ho modificato al formula brutalmente in

(FLOOR(datediff(day, [Data di nascita], getdate()) / 365.25))

ottenendo dalla divisione il numero di anni contenuto nel numero di giorni. L'approssimazione è migliore,  ma anche questa soluzione non è evidentemente corretta.

9 Risposte

  • Re: Calcolare età - 2

    Oppure puoi scomporre la formulain DUE parti:

    una parte che considera l'anno di nascita FINO al 31/12/anno precedente all'anno di interesse

    la seconda parte, che prende in considerazione l'anno di interesse, che vale 0 SE la data (gg/mm) e' < al gg/mm di nascita, 1 altrimenti

  • Re: Calcolare età - 2

    MMH… Mica facile. La formula va in una colonna calcolata.

    (DATADIFF(year,[Data di nascita], DATEFROMPARTS(YEAR(GETDATE())-1,12,31)) + IIF(DATEPART(dayofyear,GETDATE())>DATEPART(dayofyear,[Data di nascita]),1,0))

    Funzionerà? Grazie comunque.

    Comunque la domanda rimane, anche se accademica: esiste un equivalente sqlserver per la formula (senz'altro più semplice) in mysql?

  • Re: Calcolare età - 2

    Vedi se questa ti va bene nel qual caso puoi adattarla alla colonna calcolata

    declare @dn date='20220917'
          ,@dNow datetime ='20230916'
    select datediff(year, @dn, @dnow) as EtaApprossimataInAnni
         ,-case when dateadd(year, datediff(year, @dn, @dnow), @dn)>@dnow then 1 else 0 end as CorrezioneEtaAnni
      ,datediff(year, @dn, @dnow) - case when dateadd(year, datediff(year, @dn, @dnow), @dn)>@dnow then 1 else 0 end as EtaCorretta

    P.S:

    occhio che se restituisce valori negativi forse c'è qualcosa che non va e forse dovrebbe restituire 0

    comunque facile da aggiustare

  • Re: Calcolare età - 2

    Ho inserito la formula di cui al mio ultimo post nella colonna calcolata, e sembra funzionare.

    Per sspintux: confesso la mia attuale impreparazione, ma sto tentando di capire che cosa faccia quel pezzo di codice. P.es., datediff(year,@dn,@dnow), con i valori dati non è sempre uguale a 1? Credo ia solo un esempio e @dn sta per DataNascita, e analogamente  datetime dovrebbe essere uguale a getdate(), ma non ne sono certo…

    Probabilmente non conosco abbastanza lo SQL

  • Re: Calcolare età - 2

    Salve, 

    buona la formulazione di @spintux, che penso legata a letture su Itzik Ben Gan, grande matematico e geniale SQL Server trainer, autore di innumerevoli libri di T-SQL querying…

    oltre a quella formulazione, Itzik propone anche una soluzione basata sulla “differenza” numerica (decimale e non su base annua 365) tra le date espresse in formato yyyyMMdd, quindi

    evento: 20200229 (bisestile)
    data nascita: 19680229 (bisestile)
    differenza = 520.000

    e quindi dividendo il risultato per 10.000 mantenendo la sola parte intera…

    
    DECLARE
     @birthdate AS DATETIME = '1968-02-29'
     ,@eventdate AS DATETIME = '2020-02-29'
    
    SELECT
     (CAST(CONVERT(CHAR(8),@eventdate,112) AS INT)
      - CAST(CONVERT(CHAR(8),@birthdate,112) AS INT)) / 10000 AS Age;
    --< ----------
    Age
    -----------
    52
    
    

    la soluzione viene attribuita a Craig Pessano

    e' semplice, immediatamente comprensibile, e richiede “solo” 4 conversioni intermedie, a differenza delle soluzioni sopra indicate… e' veramente brillante…

    salutoni romagnoli
    – 
    Andrea

  • Re: Calcolare età - 2

    Non ho capito perchè funziona (sono un po' lento), ma funziona: con qualche adattamento inserisco la formula nella colonna calcolata

    (floor((convert(int,convert(char(8),getdate(),112))  - convert(int,convert(char(8),[Data di nascita],112))) / 10000))

    e funziona

  • Re: Calcolare età - 2

    Salve roberto21…

    perche' usi il FLOOR e tutto il resto?

    e' sufficiente

    (CAST(CONVERT(CHAR(8),GETDATE(),112) AS INT)
      - CAST(CONVERT(CHAR(8),[Data di nascita],112) AS INT)) / 10000 

    salutoni romagnoli
    – 
    Andrea

  • Re: Calcolare età - 2

    Pensavo mi servisse per eliminare i decimali dalla divisione per 10000, ma hai ragione, non serve. Come ho detto, sto imparando: anche la sostituzione di cast con convert, anche se funziona, non serve. Il fatto è che, sbagliando, non mettevo  “as int”, quindi beccavo un errore, e avevo messo convert(int….) al suo posto. Si impara sempre. Grazie mille.

  • Re: Calcolare età - 2

    19/03/2023 - asql ha scritto:


    … letture su Itzik Ben Gan, grande matematico e geniale SQL Server trainer, autore di innumerevoli libri di T-SQL querying…

    Ciao, 

    [OT]

    la prima volta che ne sentii parlare rimasi affascinato da questa idea ( oltre le altre) 

    per generare numeri sequenziali che , a memoria , suonava cosi

    select b0 + b1*2 + b2*4 as N
    from
    (select 0 as b0 union all select 1 ) B0
    cross join 
    (select 0 as b1 union all select 1 ) B1
    cross join 
    (select 0 as b2 union all select 1 ) B2
    order by N
    
Devi accedere o registrarti per scrivere nel forum
9 risposte