Je reçois des rapports dans lesquels les données sont ETL
dans la base de données automatiquement. J'extrais et transformais certaines de ces données pour les charger ailleurs. Une chose que je dois faire est une DATEDIFF
, mais l'année doit être exacte (c'est-à-dire 4,6 ans au lieu d'être arrondie à cinq ans.
Ce qui suit est mon script:
select *, DATEDIFF (yy, Begin_date, GETDATE()) AS 'Age in Years'
from Report_Stage;
La colonne 'Age_In_Years'
est en cours d’arrondissement. Comment puis-je obtenir la date exacte en années?
Avez-vous essayé d’obtenir la différence en mois et de calculer les années de cette façon? Par exemple, 30 mois/12 équivaudrait à 2,5 ans.
Edit: Cette requête SQL contient plusieurs approches pour calculer la différence de date:
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
Tout datediff()
do calcule le nombre de limites de période franchies entre les dates to. Par exemple
datediff(yy,'31 Dec 2013','1 Jan 2014')
renvoie 1.
Vous obtiendrez un résultat plus précis si vous calculez la différence entre les deux dates en jours et que vous divisez par la longueur moyenne d'une année civile en jours sur une période de 400 ans (365.2425):
datediff(day,{start-date},{end-date},) / 365.2425
Par exemple,
select datediff(day,'1 Jan 2000' ,'18 April 2014') / 365.2425
return 14.29461248
- arrondissez-le simplement à la précision souhaitée.
Je pense que la division par 365.2425 n’est pas un bon moyen de le faire. Aucune division ne peut y parvenir avec une précision absolue (l’utilisation de 365.25 pose également des problèmes).
Je sais que le script suivant calcule une différence de date précise (bien que ce ne soit peut-être pas le moyen le plus rapide):
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
En comparaison:
select datediff(day,@d1 ,@d2) / 365.2425
-- = 115 years => wrong!
Vous pourriez peut-être calculer de petites plages avec la division, mais pourquoi tenter le coup ??
Le script suivant peut aider à tester les fonctions yeardiff (il suffit de permuter le cast (dateiff (jour, @ d1, @ d2)/365.2425 en tant qu'int) en fonction de la fonction):
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
J'ai trouvé une meilleure solution. Cela suppose que la première date est inférieure ou égale à la deuxième date.
declare @dateTable table (date1 datetime, date2 datetime)
insert into @dateTable
select '2017-12-31', '2018-01-02' union
select '2017-01-03', '2018-01-02' union
select '2017-01-02', '2018-01-02' union
select '2017-01-01', '2018-01-02' union
select '2016-12-01', '2018-01-02' union
select '2016-01-03', '2018-01-02' union
select '2016-01-02', '2018-01-02' union
select '2016-01-01', '2018-01-02'
select date1, date2,
case when ((DATEPART(year, date1) < DATEPART(year, date2)) and
((DATEPART(month, date1) <= DATEPART(month, date2)) and
(DATEPART(day, date1) <= DATEPART(day, date2)) ))
then DATEDIFF(year, date1, date2)
when (DATEPART(year, date1) < DATEPART(year, date2))
then DATEDIFF(year, date1, date2) - 1
when (DATEPART(year, date1) = DATEPART(year, date2))
then 0
end [YearsOfService]
from @dateTable
date1 date2 YearsOfService
----------------------- ----------------------- --------------
2016-01-01 00:00:00.000 2018-01-02 00:00:00.000 2
2016-01-02 00:00:00.000 2018-01-02 00:00:00.000 2
2016-01-03 00:00:00.000 2018-01-02 00:00:00.000 1
2016-12-01 00:00:00.000 2018-01-02 00:00:00.000 1
2017-01-01 00:00:00.000 2018-01-02 00:00:00.000 1
2017-01-02 00:00:00.000 2018-01-02 00:00:00.000 1
2017-01-03 00:00:00.000 2018-01-02 00:00:00.000 0
2017-12-31 00:00:00.000 2018-01-02 00:00:00.000 0