Mam tabelę z listą osób wraz z ich datą urodzenia (obecnie nvarchar (25))
Jak mogę przekształcić to w datę, a następnie obliczyć ich wiek w latach?
Moje dane wyglądają następująco
ID Name DOB
1 John 1992-01-09 00:00:00
2 Sally 1959-05-20 00:00:00
Chciałbym zobaczyć:
ID Name AGE DOB
1 John 17 1992-01-09 00:00:00
2 Sally 50 1959-05-20 00:00:00
Odpowiedzi:
Występują problemy z rokiem / dniami przestępnymi i następującą metodą, zobacz aktualizację poniżej:
AKTUALIZUJ tutaj kilka dokładniejszych metod:
NAJLEPSZA METODA NA LATA W INT
możesz zmienić powyższe
10000
na10000.0
i uzyskać ułamki dziesiętne, ale nie będzie to tak dokładne, jak metoda poniżej.NAJLEPSZA METODA LAT W UDZIALE UMIESZCZONYM
źródło
GETDATE()
) w dniu `` 2013-07-04 23:59:59 '', to mówi: I Mam 27 lat, podczas gdy w tej chwili jeszcze nie jestem. Przykładowy kod:declare @startDate nvarchar(100) = '1986-07-05 00:00:00' declare @endDate nvarchar(100) = '2013-07-04 23:59:59' SELECT DATEDIFF(hour,@startDate,@endDate)/8766.0 AS AgeYearsDecimal ,CONVERT(int,ROUND(DATEDIFF(hour,@startDate,@endDate)/8766.0,0)) AS AgeYearsIntRound ,DATEDIFF(hour,@startDate,@endDate)/8766 AS AgeYearsIntTrunc
select datediff(year, '2000-01-05', '2018-01-04')
zwraca 18, a nie 17, jak powinno. Skorzystałem z powyższego przykładu pod nagłówkiem „NAJLEPSZA METODA NA LATA W INT” i działa idealnie. Dzięki!Muszę to wyrzucić. Jeśli przekonwertujesz datę za pomocą stylu 112 (rrrrmmdd) na liczbę, możesz użyć takiego obliczenia ...
(rrrrMMdd - rrrrMMdd) / 10000 = różnica w pełnych latach
wynik
źródło
code: SELECT [Age] = (0+ FORMAT(@as_of,'yyyyMMdd') - FORMAT(@bday,'yyyyMMdd') ) /10000 --The 0+ part tells SQL to calc the char(8) as numbers
Używam tego zapytania w naszym kodzie produkcyjnym przez prawie 10 lat:
źródło
DATEDIFF(yy, @BirthDate, GETDATE()) - CASE WHEN (MONTH(@BirthDate) >= MONTH(GETDATE())) AND DAY(@BirthDate) > DAY(GETDATE()) THEN 1 ELSE 0 END
CASE WHEN (MONTH(@date) > MONTH(GETDATE())) OR (MONTH(@date) = MONTH(GETDATE()) AND DAY(@date) > DAY(GETDATE())) THEN 1 ELSE 0 END
Tak wiele z powyższych rozwiązań jest błędnych DateDiff (yy, @ Dob, @PassedDate) nie uwzględni miesiąca i dnia obu dat. Również branie części do rzutek i porównywanie działa tylko wtedy, gdy są odpowiednio zamówione.
NASTĘPUJĄCY KOD DZIAŁA I JEST BARDZO PROSTY:
źródło
0925
(lub925
). Robi to samo z bieżącą datą (na przykład 16 grudnia staje się1216
), a następnie sprawdza, czy wartość całkowita DoB już przeszła. Aby utworzyć tę liczbę całkowitą, należy pomnożyć miesiąc przez 100.(CONVERT(int,CONVERT(char(8),@Now,112))-CONVERT(char(8),@Dob,112))/10000
Musisz wziąć pod uwagę sposób zaokrągleń komendy datediff.
Które zaadaptowałem stąd .
Należy pamiętać, że data 28 lutego będzie traktowana jako data urodzin skoczka w przypadku lat innych niż przestępne, np. Osoba urodzona 29 lutego 2020 r. Będzie uważana za roczną 28 lutego 2021 r. Zamiast 1 marca 2021 r.
źródło
SELECT DATEDIFF(year, DOB, getdate()) + CASE WHEN (DATEADD(year,DATEDIFF(year, DOB, getdate()) , DOB) > getdate()) THEN - 1 ELSE 0 END)
EDYCJA: TA ODPOWIEDŹ JEST NIEPRAWIDŁOWA. Zostawiam to tutaj jako ostrzeżenie dla każdego, kto ma ochotę użyć
dayofyear
, z dalszą edycją na końcu.Jeśli, tak jak ja, nie chcesz dzielić przez ułamkowe dni lub ryzykować błędów zaokrągleń / lat przestępnych, pochwalam komentarz @Bacon Bits w poście nad https://stackoverflow.com/a/1572257/489865, gdzie mówi:
Następnie oferuje:
Jest tu kilka sugestii dotyczących porównania miesiąca i dnia (a niektórzy mylą się, nie dopuszczając, aby
OR
tak było poprawnie tutaj!). Ale nikt nie zaoferowałdayofyear
, co wydaje się tak proste i znacznie krótsze. Proponuję:[Uwaga: nigdzie w SQL BOL / MSDN
DATEPART(dayofyear, ...)
zwroty nie są faktycznie udokumentowane! Rozumiem, że jest to liczba z zakresu 1--366; co najważniejsze, nie zmienia się według ustawień regionalnych zgodnie zDATEPART(weekday, ...)
&SET DATEFIRST
.]EDIT: Dlaczego
dayofyear
idzie źle : Jako użytkownik @AeroX skomentował, czy narodziny / data rozpoczęcia jest po lutego w roku przestępnym nie wiek jest o jeden dzień wcześniej, gdy bieżąca data zakończenia / jest rokiem przestępnym, na przykład'2015-05-26'
,'2016-05-25'
daje wiek 1, kiedy powinno nadal wynosić 0. Porównywanie latdayofyear
w różnych latach jest wyraźnie niebezpieczne. Więc używanieMONTH()
iDAY()
jest w końcu konieczne.źródło
DayOfYear
metody.dayofyear
, ale zostało wyraźnie zredagowane, aby pokazać, dlaczego idzie źle. Mam nadzieję, że to jest odpowiednie.Ponieważ nie ma jednej prostej odpowiedzi, która zawsze podaje właściwy wiek, oto, co wymyśliłem.
W ten sposób uzyskuje się roczną różnicę między datą urodzenia a datą bieżącą. Następnie odejmuje rok, jeśli data urodzenia jeszcze nie minęła.
Dokładne przez cały czas - niezależnie od lat przestępnych lub tego, jak blisko daty urodzenia.
A co najlepsze - brak funkcji.
źródło
źródło
Co powiesz na:
Czy nie pozwoliłoby to uniknąć tych wszystkich zaokrągleń, obcinania i rozwiązywania problemów?
źródło
'1986-07-05 00:00:00'
za DOB i'2013-07-04 23:59:59'
na bieżący czas.Wydaje mi się, że jest to podobne do innych zamieszczonych tutaj .... ale to rozwiązanie działało w przykładach z lat przestępnych od 02/29/1976 do 03/01/2011, a także działało w przypadku w pierwszym roku .. jak 07/04 / 2011 do 07/03/2012, który ostatni opublikował o rozwiązaniu roku przestępnego, nie działał w przypadku użycia w pierwszym roku.
Znaleziono tutaj .
źródło
źródło
źródło: http://beginsql.wordpress.com/2012/04/26/how-to-calculate-age-in-sql-server/
źródło
code: SELECT [Age] = (0+ FORMAT(@ToDate,'yyyyMMdd') - FORMAT(@DOB,'yyyyMMdd') ) /10000
Dużo myślałem i szukałem w tej sprawie i mam 3 rozwiązania
Oto wartości testowe:
Rozwiązanie 1: Znalazłem to podejście w jednej bibliotece js. To jest moje ulubione.
W rzeczywistości dodaje różnicę lat do DOB, a jeśli jest większa niż bieżąca data, odejmuje jeden rok. Proste, prawda? Tyle tylko, że tutaj powielają się różnice lat.
Ale jeśli nie potrzebujesz go używać w tekście, możesz napisać to w ten sposób:
Rozwiązanie 2: Ten, który pierwotnie skopiowałem z @ bacon-bits. Najłatwiejszy do zrozumienia, ale trochę długi.
To w zasadzie obliczanie wieku, tak jak my, ludzie.
Rozwiązanie 3: Mój przyjaciel przerobił to na to:
Ten jest najkrótszy, ale najtrudniejszy do zrozumienia.
50
to tylko waga, więc różnica dni jest ważna tylko wtedy, gdy miesiące są takie same.SIGN
Funkcja służy do przekształcania dowolnej otrzymanej wartości na -1, 0 lub 1.CEILING(0.5 *
jest tym samymMath.max(0, value)
, co w SQL, ale nie ma czegoś takiego.źródło
źródło
Jest tutaj wiele odpowiedzi 365,25. Pamiętaj, jak zdefiniowano lata przestępne:
źródło
Co powiesz na to:
źródło
Spróbuj tego
źródło
Wypróbuj to rozwiązanie:
źródło
To poprawnie rozwiąże problemy z datą urodzenia i zaokrąglaniem:
źródło
Rozwiązanie Eda Harpera jest najprostszym, jakie znalazłem, i nigdy nie zwraca złej odpowiedzi, gdy miesiąc i dzień dwóch dat są oddalone o 1 lub mniej dni. Dokonałem niewielkiej modyfikacji, aby poradzić sobie z negatywnymi wiekami.
źródło
Odpowiedź oznaczona jako poprawna jest bliższa dokładności, ale zawodzi w następującym scenariuszu - gdzie rok urodzenia to rok przestępny i dzień po miesiącu lutym
LUB
- Poniższe rozwiązanie daje mi dokładniejsze wyniki.
Działał w prawie wszystkich scenariuszach, biorąc pod uwagę rok przestępny, datę 29 lutego itp.
Proszę mnie poprawić, jeśli ta formuła ma jakąkolwiek lukę.
źródło
floor
.źródło
Oto jak obliczam wiek na podstawie daty urodzenia i aktualnej daty.
źródło
źródło
month(compare) > month(dob)
ALEday(compare) < day(dob)
, npselect dbo.AgeAtDate('2000-01-14', '2016-02-12')
.źródło
A co z rozwiązaniem zawierającym tylko funkcje daty, a nie matematykę, bez obaw o rok przestępny
źródło
Po wypróbowaniu WIELU metod działa to w 100% przypadków przy użyciu nowoczesnej funkcji MS SQL FORMAT zamiast konwertowania do stylu 112. Albo zadziała, ale jest to najmniejszy kod.
Czy ktoś może znaleźć niedziałającą kombinację dat? Chyba nie ma :)
źródło
Użyliśmy czegoś takiego jak tutaj, ale biorąc pod uwagę średni wiek:
Zwróć uwagę, ROUND jest raczej na zewnątrz niż wewnątrz. Dzięki temu AVG będzie dokładniejsze, a ROUND tylko raz. Robiąc to też szybciej.
źródło
źródło
źródło