2008-11-12 14 views
8

W bazie danych SQL Server zapisuję datę urodzenia osób. Czy istnieje prosta metoda określania wieku danej osoby w danym dniu przy użyciu tylko SQL?Znajdowanie czyjegoś wieku w SQL

Używanie DATEDIFF (ROK, DateOfBirth, GETDATE()) nie działa, ponieważ tylko patrzy na część roku. Na przykład DateDiff (rok, '31 grudnia 2007' roku, '01 stycznia 2008') zwrotów 1.

Odpowiedz

21

Sprawdź ten artykuł: How to calculate age of a person using SQL codes

Oto kod z artykułu:

DECLARE @BirthDate DATETIME 
DECLARE @CurrentDate DATETIME 

SELECT @CurrentDate = '20070210', @BirthDate = '19790519' 

SELECT DATEDIFF(YY, @BirthDate, @CurrentDate) - CASE WHEN((MONTH(@BirthDate)*100 + DAY(@BirthDate)) > (MONTH(@CurrentDate)*100 + DAY(@CurrentDate))) THEN 1 ELSE 0 END 
+2

Czy mógłbyś umieścić odpowiedni kod w swojej odpowiedzi? Linki do innych stron internetowych mogą (i są) łamane, więc w przyszłości ta odpowiedź może nie być przydatna, jeśli link przestanie działać. –

+0

@ Przyspiesz C +1 za sugestię dodawania kodu, ponieważ witryna jest obecnie wyłączona, a ta odpowiedź byłaby bezużyteczna z tylko linkiem. –

5

jest też inny sposób, że jest nieco prostsze:

Select CAST(DATEDIFF(hh, [birthdate], GETDATE())/8766 AS int) AS Age 

Ponieważ zaokrąglanie tutaj jest bardzo ziarnisty, to jest prawie idealnie dokładne. Wyjątki są tak zawiłe, że są niemal żartobliwe: co czwarty rok powracający wiek będzie o jeden rok za młody, jeśli A) zapytamy o wiek przed 6:00, B) w dniu urodzin danej osoby i C) ich urodziny są po 28 lutego. W moim otoczeniu jest to całkowicie dopuszczalny kompromis.

+0

Jeśli zastąpisz GETDATE() wartością statyczną, trafisz wyjątek częściej, ponieważ sprawdzasz o północy. Wygląda na to, że sprawdzi się sprawdzenie od południa, a nie od północy. – Guvante

2

FWIW, Wiek można obliczyć w prosty sposób, bez uciekania się do sztuczek (nie, że jest coś nie tak z hacków!):

CREATE FUNCTION Age (@BirthDate DATETIME) 
RETURNS INT 
AS 
BEGIN 
    DECLARE @AgeOnBirthdayThisYear INT 
    DECLARE @BirthdayThisYear DATETIME 
    SET @AgeOnBirthdayThisYear = DATEDIFF(year, @BirthDate, GETDATE()) 
    SET @BirthdayThisYear = DATEADD(year, @AgeOnBirthdayThisYear, @BirthDate) 
    RETURN 
     @AgeOnBirthdayThisYear 
     - CASE WHEN @BirthdayThisYear > GETDATE() THEN 1 ELSE 0 END 
END 
1

Rozwiązanie to pokazać, jak w jednej kwerendzie bez zmiennych

SELECT DATEDIFF(YY, birthdate, GETDATE()) - CASE WHEN((MONTH(birthdate)*100 + DAY(birthdate)) > (MONTH(GETDATE())*100 + DAY(GETDATE()))) THEN 1 ELSE 0 END 
1

to jest bardziej zwięzły i nieco szybciej niż odpowiedzi pod warunkiem, dokładne i całkowicie:

datediff(year,DateOfBirth,getdate()-datepart(dy,DateOfBirth)+1) 
+0

Ta metoda nie działa, gdy GetDate() jest datą urodzenia. Oto przykład, w którym dana osoba powinna mieć 40 lat, ale zwraca tylko 39. "SELECT datediff (rok" 1/29/1973 ", CAST (" 1/29/2013 "AS DATETIME) -datepart (dy, '1/29/1973 ')) ' –

+0

Dzięki! Naprawiony. ------- – brianary

0

Mam nadzieję, że ten jest idealny, pod warunkiem, że zaakceptujesz algorytm, że dziecko-skaczarka przewraca rok o kolejne 29 lutego lub 1 marca w lata wolne od skoku. @DOB musi zawierać datę w ciągu kilku stuleci teraz musi @AsOf zawierają podobną datę> = @DOB:

SET @Age = YEAR(@AsOf) - YEAR(@DOB) - 1 
IF MONTH(@AsOf) * 100 + DAY(@AsOf) >= MONTH(@DOB) * 100 + DAY(@DOB) 
    SET @Age = @Age + 1 

bym naprawdę bardzo wdzięczni za wszelkie testy i komentarze jak już nie znalazł sposób jeszcze go złamać ... jeszcze.

dodane - 31.01.2014: To wydaje się doskonale pracować zbyt chociaż na pierwszy rzut oka wygląda to zbyt surowy:

SET @Age = FLOOR(DATEDIFF(dd,@DOB,@CompareDate)/365.25) 

Pop to w funkcji i oto skrypt testowy:

SELECT dbo.fnGetAge('2/27/2008', '2/27/2012') 
    SELECT dbo.fnGetAge('2/27/2008', '2/28/2012') 
    SELECT dbo.fnGetAge('2/27/2008', '2/29/2012') 
    SELECT dbo.fnGetAge('2/27/2008', '3/1/2012') 
    -- 4 4 4 4 
    SELECT dbo.fnGetAge('2/28/2008', '2/27/2012') 
    SELECT dbo.fnGetAge('2/28/2008', '2/28/2012') 
    SELECT dbo.fnGetAge('2/28/2008', '2/29/2012') 
    SELECT dbo.fnGetAge('2/28/2008', '3/1/2012') 
    -- 3 4 4 4 
    SELECT dbo.fnGetAge('2/29/2008', '2/27/2012') 
    SELECT dbo.fnGetAge('2/29/2008', '2/28/2012') 
    SELECT dbo.fnGetAge('2/29/2008', '2/29/2012') 
    SELECT dbo.fnGetAge('2/29/2008', '3/1/2012') 
    -- 3 3 4 4 
    SELECT dbo.fnGetAge('3/1/2008', '2/27/2012') 
    SELECT dbo.fnGetAge('3/1/2008', '2/28/2012') 
    SELECT dbo.fnGetAge('3/1/2008', '2/29/2012') 
    SELECT dbo.fnGetAge('3/1/2008', '3/1/2012') 
    -- 3 3 3 4 
    SELECT dbo.fnGetAge('3/1/2007', '2/27/2012') 
    SELECT dbo.fnGetAge('3/1/2007', '2/28/2012') 
    SELECT dbo.fnGetAge('3/1/2007', '2/29/2012') 
    SELECT dbo.fnGetAge('3/1/2007', '3/1/2012') 
    -- 4 4 4 5 
    SELECT dbo.fnGetAge('3/1/2007', '2/27/2013') 
    SELECT dbo.fnGetAge('3/1/2007', '2/28/2013') 
    SELECT dbo.fnGetAge('3/1/2007', '3/1/2013') 
    SELECT dbo.fnGetAge('2/27/2007', '2/28/2013') 
    SELECT dbo.fnGetAge('2/28/2007', '2/28/2014') 
    -- 5 5 6 6 7 

Cheers

PS: prawdopodobnie można dostosować decyzję 29 lutego do bycia dzień wcześniej, czy to pływa łodzią.

0
SELECT Pname, DOB, DATEDIFF(YEAR, DOB, GETDATE()) AS Age 
FROM tablename 
+0

małe wyjaśnienie może przejść długą drogę – davejal

Powiązane problemy