Нахождение чьего-либо возраста в SQL - PullRequest
8 голосов
/ 12 ноября 2008

В базе данных SQL Server я записываю дату рождения людей. Существует ли простой метод определения возраста человека на конкретную дату с использованием только SQL?

Использование DATEDIFF (YEAR, DateOfBirth, GETDATE ()) не работает, так как это только смотрит на часть года в дате. Например, DATEDIFF (ГОД, «31 декабря 2007», «01 января 2008») возвращает 1.

Ответы [ 7 ]

21 голосов
/ 12 ноября 2008

Ознакомьтесь с этой статьей: Как рассчитать возраст человека с помощью кодов SQL

Вот код из статьи:

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 
5 голосов
/ 18 марта 2009

Есть еще один способ, который немного проще:

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

Поскольку округление здесь очень гранулированное, это почти совершенно точно. Исключения настолько запутанны, что они почти смешны: каждый четвертый год возвращаемый возраст будет на один год моложе, если мы а) спросим возраст до 6:00 утра, б) в день рождения человека и в) его день рождения после 28 февраля В моих условиях это вполне приемлемый компромисс.

2 голосов
/ 31 января 2012

FWIW, возраст можно вычислить простым способом, не прибегая к взломам (не то, что с взломами что-то не так!):

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 голос
/ 23 октября 2012

Это более кратко и немного быстрее, чем предоставленные ответы, и совершенно точно:

datediff(year,DateOfBirth,getdate()-datepart(dy,DateOfBirth)+1)
1 голос
/ 08 октября 2012

Это решение показывает, как в одном запросе без переменных

SELECT DATEDIFF(YY, birthdate, GETDATE()) - CASE WHEN( (MONTH(birthdate)*100 + DAY(birthdate)) > (MONTH(GETDATE())*100 + DAY(GETDATE())) ) THEN 1 ELSE 0 END
0 голосов
/ 13 января 2016
SELECT Pname, DOB, DATEDIFF(YEAR, DOB, GETDATE()) AS Age
FROM tablename
0 голосов
/ 31 января 2014

Я надеюсь, что этот вариант идеален, если вы примете алгоритм, согласно которому ребенок-високосник становится на год старше 29 февраля или 1 марта в не високосные годы. @DOB должен содержать дату в течение нескольких столетий, @AsOf должен содержать аналогичную дату> = @DOB:

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

Я ДЕЙСТВИТЕЛЬНО ДЕЙСТВИТЕЛЬНО оценил бы любое тестирование и комментарии, поскольку я еще не нашел способ сломать его ... пока.

Добавлено - 31.01.2014: Кажется, что этот тоже отлично работает, хотя на первый взгляд выглядит слишком грубо:

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

Вставьте их в функцию и вот тестовый скрипт:

    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

Приветствия

PS: Вероятно, вы можете изменить решение от 29 февраля на день раньше, если это пропустит вашу лодку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...