it-swarm.com.de

Berechnen des Alters (in Jahren) basierend auf Geburtsdatum und getDate ()

Ich habe eine Tabelle mit Personen und ihrem Geburtsdatum (derzeit nvarchar (25)).

Wie kann ich das in ein Datum umwandeln und dann das Alter in Jahren berechnen?

Meine Daten sehen wie folgt aus

ID    Name   DOB
1     John   1992-01-09 00:00:00
2     Sally  1959-05-20 00:00:00

Ich würde gerne ... sehen:

ID    Name   AGE  DOB
1     John   17   1992-01-09 00:00:00
2     Sally  50   1959-05-20 00:00:00
140
Jimmy

Es gibt Probleme mit Schaltjahrtagen und der folgenden Methode, siehe Update unten:

versuche dies:

DECLARE @dob  datetime
SET @dob='1992-01-09 00:00:00'

SELECT DATEDIFF(hour,@dob,GETDATE())/8766.0 AS AgeYearsDecimal
    ,CONVERT(int,ROUND(DATEDIFF(hour,@dob,GETDATE())/8766.0,0)) AS AgeYearsIntRound
    ,DATEDIFF(hour,@dob,GETDATE())/8766 AS AgeYearsIntTrunc

AUSGABE:

AgeYearsDecimal                         AgeYearsIntRound AgeYearsIntTrunc
--------------------------------------- ---------------- ----------------
17.767054                               18               17

(1 row(s) affected)

/ - _ update _ Hier sind einige genauere Methoden:

BESTE METHODE FÜR JAHRE IN INT

DECLARE @Now  datetime, @Dob datetime
SELECT   @Now='1990-05-05', @Dob='1980-05-05'  --results in 10
--SELECT @Now='1990-05-04', @Dob='1980-05-05'  --results in  9
--SELECT @Now='1989-05-06', @Dob='1980-05-05'  --results in  9
--SELECT @Now='1990-05-06', @Dob='1980-05-05'  --results in 10
--SELECT @Now='1990-12-06', @Dob='1980-05-05'  --results in 10
--SELECT @Now='1991-05-04', @Dob='1980-05-05'  --results in 10

SELECT
    (CONVERT(int,CONVERT(char(8),@Now,112))-CONVERT(char(8),@Dob,112))/10000 AS AgeIntYears

sie können den obigen 10000 in 10000.0 ändern und Dezimalzahlen erhalten, dies ist jedoch nicht so genau wie die unten beschriebene Methode.

BESTE METHODE FÜR JAHRE IN DEKIMAL

DECLARE @Now  datetime, @Dob datetime
SELECT   @Now='1990-05-05', @Dob='1980-05-05' --results in 10.000000000000
--SELECT @Now='1990-05-04', @Dob='1980-05-05' --results in  9.997260273973
--SELECT @Now='1989-05-06', @Dob='1980-05-05' --results in  9.002739726027
--SELECT @Now='1990-05-06', @Dob='1980-05-05' --results in 10.002739726027
--SELECT @Now='1990-12-06', @Dob='1980-05-05' --results in 10.589041095890
--SELECT @Now='1991-05-04', @Dob='1980-05-05' --results in 10.997260273973

SELECT 1.0* DateDiff(yy,@Dob,@Now) 
    +CASE 
         WHEN @Now >= DATEFROMPARTS(DATEPART(yyyy,@Now),DATEPART(m,@Dob),DATEPART(d,@Dob)) THEN  --birthday has happened for the @now year, so add some portion onto the year difference
           (  1.0   --force automatic conversions from int to decimal
              * DATEDIFF(day,DATEFROMPARTS(DATEPART(yyyy,@Now),DATEPART(m,@Dob),DATEPART(d,@Dob)),@Now) --number of days difference between the @Now year birthday and the @Now day
              / DATEDIFF(day,DATEFROMPARTS(DATEPART(yyyy,@Now),1,1),DATEFROMPARTS(DATEPART(yyyy,@Now)+1,1,1)) --number of days in the @Now year
           )
         ELSE  --birthday has not been reached for the last year, so remove some portion of the year difference
           -1 --remove this fractional difference onto the age
           * (  -1.0   --force automatic conversions from int to decimal
                * DATEDIFF(day,DATEFROMPARTS(DATEPART(yyyy,@Now),DATEPART(m,@Dob),DATEPART(d,@Dob)),@Now) --number of days difference between the @Now year birthday and the @Now day
                / DATEDIFF(day,DATEFROMPARTS(DATEPART(yyyy,@Now),1,1),DATEFROMPARTS(DATEPART(yyyy,@Now)+1,1,1)) --number of days in the @Now year
             )
     END AS AgeYearsDecimal
218
KM.

Muss ich da rausschmeißen. Wenn Sie konvertieren das Datum unter Verwendung des 112-Stils (JJJJMMTT) in eine Zahl umwandeln, können Sie eine Berechnung wie diese verwenden ...

(JJJJMMTT - JJJJMMTT)/10000 = Differenz in vollen Jahren

declare @as_of datetime, @bday datetime;
select @as_of = '2009/10/15', @bday = '1980/4/20'

select 
    Convert(Char(8),@as_of,112),
    Convert(Char(8),@bday,112),
    0 + Convert(Char(8),@as_of,112) - Convert(Char(8),@bday,112), 
    (0 + Convert(Char(8),@as_of,112) - Convert(Char(8),@bday,112)) / 10000

ausgabe

20091015    19800420    290595  29
114
dotjoe

Ich habe diese Abfrage seit fast 10 Jahren in unserem Produktionscode verwendet:

SELECT FLOOR((CAST (GetDate() AS INTEGER) - CAST(Date_of_birth AS INTEGER)) / 365.25) AS Age
37
J__

Viele der oben genannten Lösungen sind falsch. DateDiff (yy, @ Dob, @PassedDate) berücksichtigt nicht den Monat und den Tag beider Datumsangaben. Auch das Nehmen der Dartteile und das Vergleichen funktionieren nur, wenn sie ordnungsgemäß bestellt wurden.

DER FOLGENDE CODE FUNKTIONIERT UND IS] SEHR EINFACH:

create function [dbo].[AgeAtDate](
    @DOB    datetime,
    @PassedDate datetime
)

returns int
with SCHEMABINDING
as
begin

declare @iMonthDayDob int
declare @iMonthDayPassedDate int


select @iMonthDayDob = CAST(datepart (mm,@DOB) * 100 + datepart  (dd,@DOB) AS int) 
select @iMonthDayPassedDate = CAST(datepart (mm,@PassedDate) * 100 + datepart  (dd,@PassedDate) AS int) 

return DateDiff(yy,@DOB, @PassedDate) 
- CASE WHEN @iMonthDayDob <= @iMonthDayPassedDate
  THEN 0 
  ELSE 1
  END

End
29
user2634514

Sie müssen die Art und Weise bedenken, wie der Befehl von Datediff abgerundet wird.

SELECT CASE WHEN dateadd(year, datediff (year, DOB, getdate()), DOB) > getdate()
            THEN datediff(year, DOB, getdate()) - 1
            ELSE datediff(year, DOB, getdate())
       END as Age
FROM <table>

Was ich von hier angepasst habe

15
Ed Harper

BEARBEITEN: DIESE ANTWORT IS INCORRECT. Ich lasse es hier als Warnung für alle, die in Versuchung sind benutze dayofyear, mit einem weiteren Edit am Ende.


Wenn Sie, wie ich, nicht durch gebrochene Tage oder Fehler bei der Rundung des Risikos/Schaltjahres dividieren möchten, begrüße ich @Bacon Bits Kommentar in einem Beitrag oben https://stackoverflow.com/a/1572257/489865 wo er sagt:

Wenn wir über das menschliche Alter sprechen, sollten Sie es so berechnen, wie Menschen das Alter berechnen. Es hat nichts damit zu tun, wie schnell sich die Erde bewegt und was mit dem Kalender zu tun hat. Jedes Mal, wenn derselbe Monat und Tag wie das Geburtsdatum vergeht, erhöhen Sie das Alter um 1. Dies bedeutet, dass das Folgende am genauesten ist, da es die Bedeutung von Menschen widerspiegelt, wenn sie "Alter" sagen.

Er bietet dann an:

DATEDIFF(yy, @date, GETDATE()) -
CASE WHEN (MONTH(@date) > MONTH(GETDATE())) OR (MONTH(@date) = MONTH(GETDATE()) AND DAY(@date) > DAY(GETDATE()))
THEN 1 ELSE 0 END

Es gibt hier einige Vorschläge zum Vergleichen von Monat und Tag (und einige verstehen das falsch, da OR hier nicht korrekt angegeben wurde!). Aber niemand hat dayofyear angeboten, was so einfach und viel kürzer erscheint. Ich biete:

DATEDIFF(year, @date, GETDATE()) -
CASE WHEN DATEPART(dayofyear, @date) > DATEPART(dayofyear, GETDATE()) THEN 1 ELSE 0 END

[Anmerkung: Nirgendwo in SQL BOL/MSDN ist das, was DATEPART(dayofyear, ...) zurückgibt, tatsächlich dokumentiert! Ich verstehe es als eine Zahl im Bereich von 1-366; Am wichtigsten ist jedoch, dass nicht nach Gebietsschema gemäß DATEPART(weekday, ...) & SET DATEFIRST geändert wird.


EDIT: Warum dayofyear schief geht: Als Benutzer hat @AeroX kommentiert, ob die Geburt/Das Startdatum liegt nach Februar in einem Nicht-Schaltjahr. Das Alter wird einen Tag früher erhöht, wenn das aktuelle/Enddatum ein Schaltjahr ist, z '2015-05-26', '2016-05-25' Gibt ein Alter von 1 an, wenn es noch 0 sein sollte. Der Vergleich von dayofyear in verschiedenen Jahren ist eindeutig gefährlich. Es ist also immerhin notwendig, MONTH() und DAY() zu verwenden.

8
JonBrave

Da es keine einfache Antwort gibt, die immer das richtige Alter angibt, habe ich mir das hier ausgedacht. 

SELECT DATEDIFF(YY, DateOfBirth, GETDATE()) - 
     CASE WHEN RIGHT(CONVERT(VARCHAR(6), GETDATE(), 12), 4) >= 
               RIGHT(CONVERT(VARCHAR(6), DateOfBirth, 12), 4) 
     THEN 0 ELSE 1 END AS AGE 

Dadurch wird die Jahresdifferenz zwischen dem Geburtsdatum und dem aktuellen Datum ermittelt. Dann wird ein Jahr abgezogen, wenn das Geburtsdatum noch nicht vergangen ist.

Immer genau - unabhängig von Schaltjahren oder wie nah am Geburtsdatum. 

Das Beste von allem - keine Funktion.

5
Hannover Fist

Ich glaube, das ist ähnlich wie bei anderen, die hier veröffentlicht wurden. Diese Lösung funktionierte jedoch für die Schaltjahr-Beispiele 29.02.1976 bis 01.03.2011 und auch für das erste Jahr/2011 bis 07/03/2012, die der letzte über die Lösung des Schaltjahrs veröffentlichte, funktionierte für diesen ersten Anwendungsfall nicht.

SELECT FLOOR(DATEDIFF(DAY, @date1 , @date2) / 365.25)

Gefunden hier .

3
lepert

Wie wäre es mit:

DECLARE @DOB datetime
SET @DOB='19851125'   
SELECT Datepart(yy,convert(date,GETDATE())[email protected])-1900

Würde das nicht all diese Rundungen, Verkürzungen und Aufhebungsprobleme vermeiden?

3
ub_coding

Prüfen Sie einfach, ob die unten stehende Antwort möglich ist. 

DECLARE @BirthDate DATE = '09/06/1979'

SELECT 
 (
 YEAR(GETDATE()) - YEAR(@BirthDate) - 
 CASE  WHEN (MONTH(GETDATE()) * 100) + DATEPART(dd, GETDATE()) >     
 (MONTH(@BirthDate) * 100) + DATEPART(dd, @BirthDate)
 THEN 1             
 ELSE 0             
 END        
 )
3
SELECT ID,
Name,
DATEDIFF(yy,CONVERT(DATETIME, DOB),GETDATE()) AS AGE,
DOB
FROM MyTable
2
flayto
DECLARE @DOB datetime
set @DOB ='11/25/1985'

select floor(
( cast(convert(varchar(8),getdate(),112) as int)-
cast(convert(varchar(8),@DOB,112) as int) ) / 10000
)

source: http://beginsql.wordpress.com/2012/04/26/how-to-calculate-age-in-sql-server/

1
celsowm
CASE WHEN datepart(MM, getdate()) < datepart(MM, BIRTHDATE) THEN ((datepart(YYYY, getdate()) - datepart(YYYY, BIRTH_DATE)) -1 )
     ELSE 
        CASE WHEN datepart(MM, getdate()) = datepart(MM, BIRTHDATE)
            THEN 
                CASE WHEN datepart(DD, getdate()) < datepart(DD, BIRTHDATE) THEN ((datepart(YYYY, getdate()) - datepart(YYYY, BIRTHDATE)) -1 )
                    ELSE (datepart(YYYY, getdate()) - datepart(YYYY, BIRTHDATE))
                END
        ELSE (datepart(YYYY, getdate()) - datepart(YYYY, BIRTHDATE)) END            
    END
1

Ich habe viel darüber nachgedacht und gesucht, und ich habe 3 Lösungen dafür 

  • alter richtig berechnen 
  • sind kurz (meistens)
  • sind (meistens) sehr verständlich.

Hier sind Testwerte:

DECLARE @NOW DATETIME = '2013-07-04 23:59:59' 
DECLARE @DOB DATETIME = '1986-07-05' 

Lösung 1: Ich habe diesen Ansatz in einer js-Bibliothek gefunden. Es ist mein Favorit. 

DATEDIFF(YY, @DOB, @NOW) - 
  CASE WHEN DATEADD(YY, DATEDIFF(YY, @DOB, @NOW), @DOB) > @NOW THEN 1 ELSE 0 END

Es fügt dem DOB tatsächlich einen Unterschied in Jahren hinzu, und wenn es größer als das aktuelle Datum ist, wird ein Jahr abgezogen. Einfach richtig? Das einzige ist, dass der Unterschied in Jahren hier doppelt vorhanden ist. 

Wenn Sie es jedoch nicht inline verwenden müssen, können Sie es so schreiben:

DECLARE @AGE INT = DATEDIFF(YY, @DOB, @NOW)
IF DATEADD(YY, @AGE, @DOB) > @NOW
SET @AGE = @AGE - 1

Lösung 2: Diese habe ich ursprünglich aus @ Speck-Bits kopiert. Es ist am einfachsten zu verstehen, aber etwas lang.

DATEDIFF(YY, @DOB, @NOW) - 
  CASE WHEN MONTH(@DOB) > MONTH(@NOW) 
    OR MONTH(@DOB) = MONTH(@NOW) AND DAY(@DOB) > DAY(@NOW) 
  THEN 1 ELSE 0 END

Es berechnet im Grunde das Alter wie wir Menschen. 


Lösung 3: Mein Freund hat es folgendermaßen geändert:

DATEDIFF(YY, @DOB, @NOW) - 
  CEILING(0.5 * SIGN((MONTH(@DOB) - MONTH(@NOW)) * 50 + DAY(@DOB) - DAY(@NOW)))

Dieses ist das kürzeste, aber es ist am schwersten zu verstehen. 50 ist nur ein Gewicht, daher ist der Tagesunterschied nur wichtig, wenn die Monate gleich sind. Die Funktion SIGN dient zum Umwandeln des Werts in -1, 0 oder 1. CEILING(0.5 * ist das gleiche wie Math.max(0, value), in SQL gibt es jedoch keine solche Funktion.

1
drinovc

Die Lösung von Ed Harper ist die einfachste, die ich gefunden habe. Sie gibt niemals die falsche Antwort zurück, wenn der Monat und der Tag der beiden Daten 1 oder weniger Tage auseinander liegen. Ich habe eine kleine Änderung vorgenommen, um mit dem negativen Alter umzugehen.

DECLARE @D1 AS DATETIME, @D2 AS DATETIME
SET @D2 = '2012-03-01 10:00:02'
SET @D1 = '2013-03-01 10:00:01'
SELECT
   DATEDIFF(YEAR, @D1,@D2)
   +
   CASE
      WHEN @D1<@D2 AND DATEADD(YEAR, DATEDIFF(YEAR,@D1, @D2), @D1) > @D2
      THEN - 1
      WHEN @D1>@D2 AND DATEADD(YEAR, DATEDIFF(YEAR,@D1, @D2), @D1) < @D2
      THEN 1
      ELSE 0
   END AS AGE
0
clovis517
DECLARE @FromDate DATETIME = '1992-01-2623:59:59.000', 
        @ToDate   DATETIME = '2016-08-10 00:00:00.000',
        @Years INT, @Months INT, @Days INT, @tmpFromDate DATETIME
SET @Years = DATEDIFF(YEAR, @FromDate, @ToDate)
 - (CASE WHEN DATEADD(YEAR, DATEDIFF(YEAR, @FromDate, @ToDate),
          @FromDate) > @ToDate THEN 1 ELSE 0 END) 


SET @tmpFromDate = DATEADD(YEAR, @Years , @FromDate)
SET @Months =  DATEDIFF(MONTH, @tmpFromDate, @ToDate)
 - (CASE WHEN DATEADD(MONTH,DATEDIFF(MONTH, @tmpFromDate, @ToDate),
          @tmpFromDate) > @ToDate THEN 1 ELSE 0 END) 

SET @tmpFromDate = DATEADD(MONTH, @Months , @tmpFromDate)
SET @Days =  DATEDIFF(DAY, @tmpFromDate, @ToDate)
 - (CASE WHEN DATEADD(DAY, DATEDIFF(DAY, @tmpFromDate, @ToDate),
          @tmpFromDate) > @ToDate THEN 1 ELSE 0 END) 

SELECT @FromDate FromDate, @ToDate ToDate, 
       @Years Years,  @Months Months, @Days Days
0
Masum

Versuche dies 

DECLARE @date datetime, @tmpdate datetime, @years int, @months int, @days int
SELECT @date = '08/16/84'

SELECT @tmpdate = @date

SELECT @years = DATEDIFF(yy, @tmpdate, GETDATE()) - CASE WHEN (MONTH(@date) > MONTH(GETDATE())) OR (MONTH(@date) = MONTH(GETDATE()) AND DAY(@date) > DAY(GETDATE())) THEN 1 ELSE 0 END
SELECT @tmpdate = DATEADD(yy, @years, @tmpdate)
SELECT @months = DATEDIFF(m, @tmpdate, GETDATE()) - CASE WHEN DAY(@date) > DAY(GETDATE()) THEN 1 ELSE 0 END
SELECT @tmpdate = DATEADD(m, @months, @tmpdate)
SELECT @days = DATEDIFF(d, @tmpdate, GETDATE())

SELECT Convert(Varchar(Max),@years)+' Years '+ Convert(Varchar(max),@months) + ' Months '+Convert(Varchar(Max), @days)+'days'
0
user1194101

Nachdem Sie die MANY-Methoden ausprobiert haben, funktioniert dies zu 100% mit der modernen MS SQL-Funktion FORMAT, anstatt in den Stil 112 zu konvertieren.

Kann jemand eine Datumskombination finden, die nicht funktioniert? Ich glaube nicht, dass es einen gibt :)

--Set parameters, or choose from table.column instead:

DECLARE @DOB    DATE = '2000/02/29' -- If @DOB is a leap day...
       ,@ToDate DATE = '2018/03/01' --...there birthday in this calculation will be 

--0+ part tells SQL to calc the char(8) as numbers:
SELECT [Age] = (0+ FORMAT(@ToDate,'yyyyMMdd') - FORMAT(@DOB,'yyyyMMdd') ) /10000
0
ukgav

Damit werden die Probleme mit dem Geburtstag und der Rundung korrekt behandelt:

DECLARE @dob  datetime
SET @dob='1992-01-09 00:00:00'

SELECT DATEDIFF(YEAR, '0:0', getdate()[email protected])
0
Digi314
select floor((datediff(day,0,@today) - datediff(day,0,@birthdate)) / 365.2425) as age

Es gibt hier eine Menge von 365,25 Antworten. Denken Sie daran, wie Schaltjahre definiert sind:

  • Alle vier Jahre
    • außer alle 100 Jahre
      • außer alle 400 Jahre
0
brianary

Wie wäre es mit einer Lösung mit nur Datumsfunktionen, nicht mit Mathematik, nicht mit dem Schaltjahr

CREATE FUNCTION dbo.getAge(@dt datetime) 
RETURNS int
AS
BEGIN
    RETURN 
        DATEDIFF(yy, @dt, getdate())
        - CASE 
            WHEN 
                MONTH(@dt) > MONTH(GETDATE()) OR 
                (MONTH(@dt) = MONTH(GETDATE()) AND DAY(@dt) > DAY(GETDATE())) 
            THEN 1 
            ELSE 0 
        END
END
0
fcaserio
CREATE function dbo.AgeAtDate(
    @DOB    datetime,
    @CompareDate datetime
)

returns INT
as
begin

return CASE WHEN @DOB is null
THEN 
    null
ELSE 
DateDiff(yy,@DOB, @CompareDate) 
- CASE WHEN datepart(mm,@CompareDate) > datepart(mm,@DOB) OR (datepart(mm,@CompareDate) = datepart(mm,@DOB) AND datepart(dd,@CompareDate) >= datepart(dd,@DOB))
  THEN 0 
  ELSE 1
  END
END
End

GO
0
Vova
Declare @dob datetime
Declare @today datetime

Set @dob = '05/20/2000'
set @today = getdate()

select  CASE
            WHEN dateadd(year, datediff (year, @dob, @today), @dob) > @today 
            THEN datediff (year, @dob, @today) - 1
            ELSE datediff (year, @dob, @today)
        END as Age
0

So berechne ich das Alter unter Berücksichtigung des Geburtsdatums und des aktuellen Datums.

select case 
            when cast(getdate() as date) = cast(dateadd(year, (datediff(year, '1996-09-09', getdate())), '1996-09-09') as date)
                then dateDiff(yyyy,'1996-09-09',dateadd(year, 0, getdate()))
            else dateDiff(yyyy,'1996-09-09',dateadd(year, -1, getdate()))
        end as MemberAge
go
0
Komengem

Die als richtig markierte Antwort ist näher an der Genauigkeit, schlägt jedoch im folgenden Szenario fehl - wo Geburtsjahr ist Sprungjahr und -tag sind nach dem Februar-Monat 

declare @ReportStartDate datetime = CONVERT(datetime, '1/1/2014'),
@DateofBirth datetime = CONVERT(datetime, '2/29/1948')

FLOOR(DATEDIFF(HOUR,@DateofBirth,@ReportStartDate )/8766)


OR 

FLOOR(DATEDIFF(HOUR,@DateofBirth,@ReportStartDate )/8765.82) -- Divisor is more accurate than 8766

- Die folgende Lösung liefert genauere Ergebnisse.

FLOOR(DATEDIFF(YEAR,@DateofBirth,@ReportStartDate) - (CASE WHEN DATEADD(YY,DATEDIFF(YEAR,@DateofBirth,@ReportStartDate),@DateofBirth) > @ReportStartDate THEN 1 ELSE 0 END ))

Es hat in fast allen Szenarien funktioniert, unter Berücksichtigung des Schaltjahres, des Datums als 29. Februar usw.

Bitte korrigieren Sie mich, wenn diese Formel eine Lücke aufweist. 

0
Bhushan Borole

Wie wäre es damit:

SET @Age = CAST(DATEDIFF(Year, @DOB, @Stamp) as int)
IF (CAST(DATEDIFF(DAY, DATEADD(Year, @Age, @DOB), @Stamp) as int) < 0) 
    SET @Age = @Age - 1
0
pajics

Versuchen Sie diese Lösung:

declare @BirthDate datetime
declare @ToDate datetime

set @BirthDate = '1/3/1990'
set @ToDate = '1/2/2008'
select @BirthDate [Date of Birth], @ToDate [ToDate],(case when (DatePart(mm,@ToDate) <  Datepart(mm,@BirthDate)) 
        OR (DatePart(m,@ToDate) = Datepart(m,@BirthDate) AND DatePart(dd,@ToDate) < Datepart(dd,@BirthDate))
        then (Datepart(yy, @ToDate) - Datepart(yy, @BirthDate) - 1)
        else (Datepart(yy, @ToDate) - Datepart(yy, @BirthDate))end) Age
0
snoopy