2014-04-17 17 views
8

Ricevo report in cui i dati sono automaticamente ETL nel DB. Estraggo e trasformo alcuni di quei dati per caricarlo da qualche altra parte. . Una cosa che devo fare è un DATEDIFF ma l'anno deve essere esatto (cioè, 4.6 anni invece di arrotondamento fino a cinque anniCalcola la differenza di data esatta in anni utilizzando SQL

Quello che segue è il mio script:

select *, DATEDIFF (yy, Begin_date, GETDATE()) AS 'Age in Years' 
from Report_Stage; 

La colonna 'Age_In_Years' è essere arrotondato. Come faccio ad avere la data precisa in anni?

+1

Se avete solo bisogno una cifra significativa, prova DATEDIFF (dd .. e dividi per 365. Questo non influirà sugli anni bisestili, però. –

+0

che lo renderebbe solo come, 1 + -. 1 corretto? –

+0

il suo arrotondamento ancora quando lo faccio in questo modo –

risposta

9

hai provato ricevendo la differenza in mesi, invece, per poi calcolare gli anni in quel modo? Ad esempio 30 mesi/12 sarebbe di 2,5 anni.

Edi t: Questa query SQL contiene diversi approcci per calcolare la differenza di data:

SELECT CONVERT(date, GetDate() - 912) AS calcDate 
     ,DATEDIFF(DAY, GetDate() - 912, GetDate()) diffDays 
     ,DATEDIFF(DAY, GetDate() - 912, GetDate())/365.0 diffDaysCalc 
     ,DATEDIFF(MONTH, GetDate() - 912, GetDate()) diffMonths 
     ,DATEDIFF(MONTH, GetDate() - 912, GetDate())/12.0 diffMonthsCalc 
     ,DATEDIFF(YEAR, GetDate() - 912, GetDate()) diffYears 
+0

La colonna è ancora arrotondata –

+0

@JeffOrris - ... così ha risposto alla tua domanda o no? La tua accettazione implica una cosa, ma il tuo commento è un'altra. È probabilmente _truncating_ a causa del fatto che la matematica viene eseguita esclusivamente come numeri interi (cioè, dovrebbe essere '/ 12.0' per forzare la matematica a virgola mobile, come nei commenti alla tua domanda). @ Imbalsamazione: è necessario aggiungere codice pertinente a risposte come questa, o questo dovrebbe essere chiuso. –

+0

Esempio di codice aggiunto alla risposta originale. – FumblesWithCode

9

Tutto datediff() non fa altro che calcolare il numero di confini d'epoca incrociate tra due date. Per esempio

datediff(yy,'31 Dec 2013','1 Jan 2014') 

rendimenti 1.

Si otterrà un risultato più preciso se si calcola la differenza tra le due date in giorni e dividere per la lunghezza media di un anno civile in giorni nel corso di un 400 arco dell'anno (365.2425):

datediff(day,{start-date},{end-date},)/365.2425 

Per esempio,

select datediff(day,'1 Jan 2000' ,'18 April 2014')/365.2425 

retu 14.29461248 — basta arrotondarlo alla precisione desiderata.

2

Penso che la divisione 365.2425 non sia un buon modo per farlo. Nessuna divisione può farlo in modo completamente accurato (l'uso di 365.25 ha anche problemi).

So che il seguente script calcola una precisa differenza di data (anche se potrebbe non essere il modo più veloce):

 declare @d1 datetime ,@d2 datetime 
     --set your dates eg: 
     select @d1 = '1901-03-02' 
     select @d2 = '2016-03-01' 

     select DATEDIFF(yy, @d1, @d2) - 
      CASE WHEN MONTH(@d2) < MONTH(@d1) THEN 1 
       WHEN MONTH(@d2) > MONTH(@d1) THEN 0 
       WHEN DAY(@d2) < DAY(@d1) THEN 1 
       ELSE 0 END 

     -- = 114 years 

Per fare un confronto:

  select datediff(day,@d1 ,@d2)/365.2425 
     -- = 115 years => wrong! 

si potrebbe essere in grado di calcolare i piccoli intervalli con la divisione, ma perché rischiare?

Lo script che segue può aiutare a testare yeardiff funzioni (solo Swap cast (DateDiff (giorno, @ d1, @ d2)/365,2425 come int) per tutto ciò che la funzione è):

declare @d1 datetime set @d1 = '1900-01-01' 

    while(@d1 < '2016-01-01') 
    begin 
    declare @d2 datetime set @d2 = '2016-04-01' 

    while(@d2 >= '1900-01-01') 
    begin 
     if (@d1 <= @d2 and dateadd(YEAR,  cast(datediff(day,@d1,@d2)/365.2425 as int)  , @d1) > @d2) 
     begin 
      select 'not a year!!', @d1, @d2, cast(datediff(day,@d1,@d2)/365.2425 as int) 
     end 

     set @d2 = dateadd(day,-1,@d2) 
    end 

    set @d1 = dateadd(day,1,@d1) 
    end 
Problemi correlati