У меня есть таблица со списком людей и датой их рождения (в настоящее время nvarchar (25))
Как я могу преобразовать это в дату, а затем рассчитать их возраст в годах?
Мои данные выглядят следующим образом
ID Name DOB
1 John 1992-01-09 00:00:00
2 Sally 1959-05-20 00:00:00
Я хотел бы посмотреть:
ID Name AGE DOB
1 John 17 1992-01-09 00:00:00
2 Sally 50 1959-05-20 00:00:00
sql-server
sql-server-2005
select
date
Джимми
источник
источник
Ответы:
Есть проблемы с високосным годом / днями и следующим методом, см. Обновление ниже:
ОБНОВИТЬ вот несколько более точных методов:
ЛУЧШИЙ МЕТОД НА ГОДЫ В INT
Вы можете изменить выше,
10000
чтобы10000.0
и получить десятичные, но это не будет столь же точным , как метод ниже.Лучший метод для лет в десятичном
источник
GETDATE()
) в '2013-07-04 23:59:59', это говорит, что я мне 27, а в тот момент я еще не Пример кода: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')
возвращает 18, а не 17, как должно. Я использовал пример выше под заголовком «Лучший метод для лет в INT», и он отлично работает. Спасибо!Должен выбросить это там. Если вы конвертируете дату, используя стиль 112 (ггггммдд), в число, вы можете использовать такой расчет ...
(yyyyMMdd - yyyyMMdd) / 10000 = разница в полных годах
вывод
источник
code: SELECT [Age] = (0+ FORMAT(@as_of,'yyyyMMdd') - FORMAT(@bday,'yyyyMMdd') ) /10000 --The 0+ part tells SQL to calc the char(8) as numbers
Я использовал этот запрос в нашем производственном коде почти 10 лет:
источник
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
Многие из приведенных выше решений неверны. DateDiff (yy, @ Dob, @PassedDate) не будет учитывать месяц и день обеих дат. Также взятие частей дротика и сравнение работает, только если они правильно упорядочены.
СЛЕДУЮЩИЙ КОД работает и очень прост:
источник
0925
(или925
). Он делает то же самое с текущей датой (как 16 декабря1216
) и затем проверяет, прошло ли уже целое значение DoB. Чтобы создать это целое число, месяц нужно умножить на 100.(CONVERT(int,CONVERT(char(8),@Now,112))-CONVERT(char(8),@Dob,112))/10000
Вам нужно подумать о том, как обходится команда datediff.
Который я адаптировал отсюда .
Обратите внимание, что 28 февраля будет считаться днем рождения скачка для не високосных лет, например, человек, родившийся 29 февраля 2020 года, будет считаться годовалым 28 февраля 2021 года вместо 01 марта 2021 года.
источник
SELECT DATEDIFF(year, DOB, getdate()) + CASE WHEN (DATEADD(year,DATEDIFF(year, DOB, getdate()) , DOB) > getdate()) THEN - 1 ELSE 0 END)
РЕДАКТИРОВАТЬ: ЭТО ОТВЕТ НЕПРАВИЛЬНЫЙ. Я оставляю это здесь как предупреждение для всех, кто испытывает желание использовать
dayofyear
, с дальнейшим редактированием в конце.Если, как и я, вы не хотите делить на дробные дни или рисковать ошибками округления / високосного года, я приветствую комментарий @Bacon Bits в посте выше https://stackoverflow.com/a/1572257/489865, где он говорит:
Затем он предлагает:
Здесь есть несколько предложений, связанных со сравнением месяца и дня (и некоторые ошибаются, не учитывая то,
OR
что здесь правильно!). Но никто не предложилdayofyear
, что кажется таким простым и намного короче. Я предлагаю:[Примечание: нигде в SQL BOL / MSDN не
DATEPART(dayofyear, ...)
возвращается то, что действительно задокументировано! Я понимаю, что это число в диапазоне 1--366; наиболее важно, это не изменяется языковым стандартом согласноDATEPART(weekday, ...)
&SET DATEFIRST
.]РЕДАКТИРОВАТЬ: Почему
dayofyear
идет не так : как прокомментировал пользователь @AeroX, если дата рождения / начала - после февраля в не високосный год, возраст увеличивается на один день раньше, когда текущая / конечная дата является високосным, например'2015-05-26'
,'2016-05-25'
дает возраст 1, когда он все еще должен быть 0. Сравнениеdayofyear
в разные годы явно опасно. Так что использоватьMONTH()
иDAY()
надо ведь.источник
DayOfYear
метода.dayofyear
, но четко отредактировал, чтобы показать, почему это идет не так. Я надеюсь, что это подходит.Поскольку не существует одного простого ответа, который всегда дает правильный возраст, вот что я придумал.
Получается разница в году между датой рождения и текущей датой. Затем вычитается год, если дата рождения еще не прошла.
Точно все время - независимо от високосных лет или как близко к дате рождения.
Лучше всего - без функции.
источник
источник
Что о:
Разве это не позволило бы избежать всех этих проблем округления, усечения и удаления?
источник
'1986-07-05 00:00:00'
за DOB и'2013-07-04 23:59:59'
за текущее время.Я полагаю, что это похоже на другие опубликованные здесь .... но это решение работало для примеров високосного года с 29.02.1976 по 03.01.2011, а также работало для случая в течение первого года .. как 07/04 С 2011 по 07/03/2012, которые последний раз публиковал о решении для високосного года, не подходил для первого варианта использования.
Нашел здесь .
источник
источник
источник: http://beginsql.wordpress.com/2012/04/26/how-to-calculate-age-in-sql-server/
источник
code: SELECT [Age] = (0+ FORMAT(@ToDate,'yyyyMMdd') - FORMAT(@DOB,'yyyyMMdd') ) /10000
Я много думал и искал об этом, и у меня есть 3 решения, которые
Вот значения тестирования:
Решение 1: Я нашел этот подход в одной библиотеке js. Это мой любимый.
Это фактически добавляет разницу в годах к DOB, и если она больше текущей даты, то вычитается один год. Просто верно? Единственное, что разница в годах здесь дублируется.
Но если вам не нужно использовать его в строке, вы можете написать это так:
Решение 2: Это то, что я изначально скопировал из @ bacon-bits. Это проще всего понять, но немного долго.
Это в основном подсчет возраста, как мы, люди.
Решение 3: Мой друг реорганизовал это в это:
Это самый короткий, но самый сложный для понимания.
50
это просто вес, поэтому разница в днях важна только тогда, когда месяцы совпадают.SIGN
Функция предназначена для преобразования любого значения, которое она получает в -1, 0 или 1.CEILING(0.5 *
, то же самое,Math.max(0, value)
но в SQL такого нет.источник
источник
Здесь 365.25 ответов. Помните, как определяются високосные годы:
источник
Как насчет этого:
источник
Попробуй это
источник
Попробуйте это решение:
источник
Это правильно решит проблемы с днем рождения и округлением:
источник
Решение Эда Харпера - самое простое из найденных мной, которое никогда не возвращает неправильный ответ, когда месяц и день двух дат разделены 1 или менее днями. Я сделал небольшую модификацию для обработки отрицательных возрастов.
источник
Ответ, помеченный как правильный, ближе к точности, но не соответствует следующему сценарию: где Год рождения - високосный, а день - после февраля
ИЛИ
- Следующее решение дает мне более точные результаты.
Это работало почти во всех сценариях, учитывая високосный год, дату 29 февраля и т. Д.
Пожалуйста, поправьте меня, если в этой формуле есть лазейки.
источник
floor
.источник
Вот как я могу рассчитать возраст, учитывая дату рождения и текущую дату.
источник
источник
month(compare) > month(dob)
НОday(compare) < day(dob)
, напримерselect dbo.AgeAtDate('2000-01-14', '2016-02-12')
.источник
Как насчет решения с только функциями даты, а не математики, не заботится о високосном году
источник
После попытки многих методов, это работает 100% времени, используя современную функцию MS SQL FORMAT вместо преобразования в стиль 112. Любой из них будет работать, но это наименьший код.
Может кто-нибудь найти комбинацию даты, которая не работает? Я не думаю, что есть один :)
источник
Мы использовали что-то вроде здесь, но затем взяли средний возраст:
Обратите внимание, КРУГЛЫЙ снаружи, а не внутри. Это позволит AVG быть более точным, а мы КРУГЛЫМ только один раз. Делая это быстрее тоже.
источник
источник
источник