Eu tenho uma tabela listando as pessoas junto com a data de nascimento (atualmente uma nvarchar (25))
Como posso converter isso para uma data e calcular sua idade em anos?
Meus dados são os seguintes
ID Name DOB
1 John 1992-01-09 00:00:00
2 Sally 1959-05-20 00:00:00
Eu gostaria de ver:
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
Jimmy
fonte
fonte
Respostas:
Há problemas com o ano bissexto / dia e o método a seguir, consulte a atualização abaixo:
ATUALIZAÇÃO aqui estão alguns métodos mais precisos:
MELHOR MÉTODO DE ANOS NO INT
você pode alterar o acima
10000
para10000.0
e obter decimais, mas não vai ser tão preciso quanto o método abaixo.MELHOR MÉTODO DE ANOS EM DECIMAL
fonte
GETDATE()
) em '2013-07-04 23:59:59', ele diz que eu tenho 27 anos, enquanto naquele momento ainda não estou. Código de exemplo: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')
retorna 18, não 17 como deveria. Usei o exemplo acima no título "MELHOR MÉTODO DE ANOS INT" e funciona perfeitamente. Obrigado!Tenho que jogar esse aqui fora. Se você converter a data usando o estilo 112 (aaaammdd) em um número, poderá usar um cálculo como este ...
(aaaaMMdd - aaaaMMdd) / 10000 = diferença em anos completos
resultado
fonte
code: SELECT [Age] = (0+ FORMAT(@as_of,'yyyyMMdd') - FORMAT(@bday,'yyyyMMdd') ) /10000 --The 0+ part tells SQL to calc the char(8) as numbers
Eu tenho usado essa consulta em nosso código de produção há quase 10 anos:
fonte
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
Muitas das soluções acima estão erradas. O DateDiff (aa, @ Dob, @PassedDate) não considerará o mês e o dia das duas datas. Também pegar as peças do dardo e comparar só funciona se elas forem encomendadas corretamente.
O SEGUINTE CÓDIGO FUNCIONA E É MUITO SIMPLES:
fonte
0925
(ou925
). Ele faz o mesmo com a data atual (como ocorre em 16 de dezembro1216
) e depois verifica se o valor inteiro DoB já passou. Para criar este número inteiro, o mês deve ser multiplicado por 100.(CONVERT(int,CONVERT(char(8),@Now,112))-CONVERT(char(8),@Dob,112))/10000
Você precisa considerar a maneira como o comando datatediff arredonda.
Que eu adaptei daqui .
Observe que o dia 28 de fevereiro será considerado o aniversário de um salto para anos não bissextos, por exemplo, uma pessoa nascida em 29 de fevereiro de 2020 será considerada com 1 ano em 28 de fevereiro de 2021 em vez de 01 de março de 2021.
fonte
SELECT DATEDIFF(year, DOB, getdate()) + CASE WHEN (DATEADD(year,DATEDIFF(year, DOB, getdate()) , DOB) > getdate()) THEN - 1 ELSE 0 END)
EDIT: ESTA RESPOSTA É INCORRETA. Deixo aqui como um aviso para qualquer pessoa tentada a usar
dayofyear
, com uma edição adicional no final.Se, como eu, você não quiser dividir por dias fracionários ou arriscar erros de arredondamento / ano bissexto, eu aplaudo o comentário do @Bacon Bits em uma postagem acima https://stackoverflow.com/a/1572257/489865, onde ele diz:
Ele então oferece:
Existem várias sugestões aqui que envolvem comparar mês e dia (e algumas erram, deixando de permitir o
OR
correto aqui!). Mas ninguém ofereceudayofyear
, o que parece tão simples e muito mais curto. Eu ofereço:[Nota: Em nenhum lugar no SQL BOL / MSDN está o que de
DATEPART(dayofyear, ...)
fato está documentado! Entendo que seja um número no intervalo de 1 a 366; o mais importante é que não muda por localidade conformeDATEPART(weekday, ...)
&SET DATEFIRST
.]EDIT: Por que
dayofyear
dá errado : Como usuário @AeroX comentou, se o nascimento / data de início é depois de fevereiro em um ano não bissexto, a idade é incrementado um dia antes, quando a data / end atual é um ano bissexto, por exemplo'2015-05-26'
,'2016-05-25'
dá uma 1 ano de idade, quando ainda deveria ser 0. Comparar osdayofyear
anos diferentes é claramente perigoso. Então, usandoMONTH()
eDAY()
é necessário, afinal.fonte
DayOfYear
métododayofyear
, mas claramente editado para mostrar por que isso dá errado. Espero que seja adequado.Como não há uma resposta simples que sempre dê a idade correta, eis o que eu vim.
Isso obtém a diferença do ano entre a data de nascimento e a data atual. Subtrai um ano se a data de nascimento ainda não passou.
Precisas o tempo todo - independentemente dos anos bissextos ou da proximidade da data de nascimento.
O melhor de tudo - nenhuma função.
fonte
fonte
A respeito:
Isso não evitaria todos esses problemas de arredondamento, truncamento e perturbação?
fonte
'1986-07-05 00:00:00'
usar o DOB e'2013-07-04 23:59:59'
o tempo atual.Eu acredito que isso é semelhante aos outros postados aqui .... mas essa solução funcionou para os exemplos dos anos bissextos 29/02/1976 a 01/03/2011 e também funcionou para o caso do primeiro ano. Como 07/04 / 2011 a 03/03/2012, que o último postou sobre a solução de ano bissexto, não funcionou no caso de uso do primeiro ano.
Encontrado aqui .
fonte
fonte
fonte: http://beginsql.wordpress.com/2012/04/26/how-to-calculate-age-in-sql-server/
fonte
code: SELECT [Age] = (0+ FORMAT(@ToDate,'yyyyMMdd') - FORMAT(@DOB,'yyyyMMdd') ) /10000
Eu tenho pensado muito e pesquisado sobre isso e tenho 3 soluções que
Aqui estão os valores de teste:
Solução 1: Encontrei essa abordagem em uma biblioteca js. É o meu favorito.
Na verdade, está adicionando diferença de anos ao DOB e, se for maior que a data atual, subtrai um ano. Simples né? A única coisa é que a diferença de anos é duplicada aqui.
Mas se você não precisar usá-lo em linha, pode escrevê-lo assim:
Solução 2: Este eu copiei originalmente de @ bacon-bits. É o mais fácil de entender, mas um pouco longo.
É basicamente calcular a idade como nós, humanos.
Solução 3: Meu amigo o refatorou para isso:
Este é o mais curto, mas é mais difícil de entender.
50
é apenas um peso; portanto, a diferença do dia é importante apenas quando os meses são iguais.SIGN
A função é transformar qualquer valor que obtiver em -1, 0 ou 1.CEILING(0.5 *
é o mesmo queMath.max(0, value)
mas não existe no SQL.fonte
fonte
Há muitas respostas 365,25 aqui. Lembre-se de como os anos bissextos são definidos:
fonte
Que tal agora:
fonte
Tente isto
fonte
Experimente esta solução:
fonte
Isso resolverá corretamente os problemas com o aniversário e o arredondamento:
fonte
A solução de Ed Harper é a mais simples que encontrei, que nunca retorna a resposta errada quando o mês e o dia das duas datas têm 1 ou menos dias de diferença. Fiz uma ligeira modificação para lidar com idades negativas.
fonte
A resposta marcada como correta está mais próxima da precisão, mas falha no seguinte cenário - onde o ano de nascimento é ano bissexto e dia após o mês de fevereiro
OU
- A solução a seguir está me dando resultados mais precisos.
Funcionou em quase todos os cenários, considerando o ano bissexto, a data em 29 de fevereiro, etc.
Por favor, corrija-me se esta fórmula tiver alguma brecha.
fonte
floor
.fonte
Aqui está como eu calculo a idade, dada a data de nascimento e a data atual.
fonte
fonte
month(compare) > month(dob)
MASday(compare) < day(dob)
, por exemploselect dbo.AgeAtDate('2000-01-14', '2016-02-12')
.fonte
Que tal uma solução com apenas funções de data, não matemática, não se preocupa com o ano bissexto
fonte
Depois de tentar MUITOS métodos, isso funciona 100% do tempo usando a moderna função MS SQL FORMAT em vez de converter para o estilo 112. Qualquer um deles funcionaria, mas esse é o menor código.
Alguém pode encontrar uma combinação de datas que não funcione? Eu não acho que exista um :)
fonte
Usamos algo parecido aqui, mas depois medimos a idade média:
Observe que o ROUND está fora e não dentro. Isso permitirá que o AVG seja mais preciso e ROUND apenas uma vez. Tornando mais rápido também.
fonte
fonte
fonte