生年月日とgetDate()に基づいて年齢(年単位)を計算する方法


171

私は人々を彼らの生年月日と一緒にリストするテーブルを持っています(現在は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

16
データベースのネイティブの日付または日時タイプを使用する代わりに、nvarchar(25)を使用して日付値を文字列として保存するのはなぜですか?
Jesper、

質問には2008ではなく2005のタグが付けられているため、ネイティブの「日付」タイプは使用できませんが、間違いなく日付時刻です。正確さを必要としないため、SmallDateTimeと主張することもできます。
Andrew

こんにちは、日付をvarcharとして保持する理由は、これを非SQLサーバースキーマからインポートしているためです。日付時刻(および他の日付形式)としてインポートするときにいくつかの問題があり、varcharはok
Jimmy

7
@ James.Elsey、インポートに問題があり、その結果すべての日付が有効ですか?varcharを使用してdatetimeまたはsmalldatetimeを使用しない限り、確信が持てません。インポートは機能しますが、他の問題が発生する場合があります。また、私は年齢を保存することがなかった、それは毎日変化し、ビューを使用
KMを。

@KMはい、そのデータを日付としてインポートする際に問題が発生しました。現時点で実行可能な唯一の解決策は、nvarcharとしてインポートすることでした。この選択は毎晩の仕事の一部になるので、年齢の保存は問題になりません
ジミー

回答:


256

うるう年/日と次の方法には問題があります。以下の更新を参照してください。

これを試して:

DECLARE @dob  datetime
SET @dob='1992-01-09 00:00:00'

SELECT DATEDIFF(hour,@dob,GETDATE())/8766.0 AS AgeYearsDecimal
    ,CONVERT(int,ROUND(DATEDIFF(hour,@dob,GETDATE())/8766.0,0)) AS AgeYearsIntRound
    ,DATEDIFF(hour,@dob,GETDATE())/8766 AS AgeYearsIntTrunc

出力:

AgeYearsDecimal                         AgeYearsIntRound AgeYearsIntTrunc
--------------------------------------- ---------------- ----------------
17.767054                               18               17

(1 row(s) affected)

ここでの更新は、いくつかのより正確な方法です:

INTでの年間の最良の方法

DECLARE @Now  datetime, @Dob datetime
SELECT   @Now='1990-05-05', @Dob='1980-05-05'  --results in 10
--SELECT @Now='1990-05-04', @Dob='1980-05-05'  --results in  9
--SELECT @Now='1989-05-06', @Dob='1980-05-05'  --results in  9
--SELECT @Now='1990-05-06', @Dob='1980-05-05'  --results in 10
--SELECT @Now='1990-12-06', @Dob='1980-05-05'  --results in 10
--SELECT @Now='1991-05-04', @Dob='1980-05-05'  --results in 10

SELECT
    (CONVERT(int,CONVERT(char(8),@Now,112))-CONVERT(char(8),@Dob,112))/10000 AS AgeIntYears

上記10000をに変更して10000.0小数を取得できますが、以下の方法ほど正確ではありません。

10年間の最良の方法

DECLARE @Now  datetime, @Dob datetime
SELECT   @Now='1990-05-05', @Dob='1980-05-05' --results in 10.000000000000
--SELECT @Now='1990-05-04', @Dob='1980-05-05' --results in  9.997260273973
--SELECT @Now='1989-05-06', @Dob='1980-05-05' --results in  9.002739726027
--SELECT @Now='1990-05-06', @Dob='1980-05-05' --results in 10.002739726027
--SELECT @Now='1990-12-06', @Dob='1980-05-05' --results in 10.589041095890
--SELECT @Now='1991-05-04', @Dob='1980-05-05' --results in 10.997260273973

SELECT 1.0* DateDiff(yy,@Dob,@Now) 
    +CASE 
         WHEN @Now >= DATEFROMPARTS(DATEPART(yyyy,@Now),DATEPART(m,@Dob),DATEPART(d,@Dob)) THEN  --birthday has happened for the @now year, so add some portion onto the year difference
           (  1.0   --force automatic conversions from int to decimal
              * DATEDIFF(day,DATEFROMPARTS(DATEPART(yyyy,@Now),DATEPART(m,@Dob),DATEPART(d,@Dob)),@Now) --number of days difference between the @Now year birthday and the @Now day
              / DATEDIFF(day,DATEFROMPARTS(DATEPART(yyyy,@Now),1,1),DATEFROMPARTS(DATEPART(yyyy,@Now)+1,1,1)) --number of days in the @Now year
           )
         ELSE  --birthday has not been reached for the last year, so remove some portion of the year difference
           -1 --remove this fractional difference onto the age
           * (  -1.0   --force automatic conversions from int to decimal
                * DATEDIFF(day,DATEFROMPARTS(DATEPART(yyyy,@Now),DATEPART(m,@Dob),DATEPART(d,@Dob)),@Now) --number of days difference between the @Now year birthday and the @Now day
                / DATEDIFF(day,DATEFROMPARTS(DATEPART(yyyy,@Now),1,1),DATEFROMPARTS(DATEPART(yyyy,@Now)+1,1,1)) --number of days in the @Now year
             )
     END AS AgeYearsDecimal

24
これも正確な解決策ではありません。私が自分の@dobを「1986-07-05 00:00:00」にして、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
bartlaarhoven 2013

20
年間8766時間を想定しているため、これは正確ではなく、365.25日になります。365.25日の年はないため、これは人の生年月日付近では、正しいよりも頻繁に不正確になります。 この方法はまだより正確です。
ベーコンビット2014年

1
2番目の@ベーコンビットのコメント-現在の日付が人の誕生日に近い場合、これは多くの場合間違っています。
2014

2
テキストの最初のブロックはこの答えを混乱させると思います。うるう年の問題が更新されたメソッドに問題がない場合、私は(本当にそれを維持したい場合は)答えの下部に移動することをお勧めします。
ajbeaven 2017

1
あなたがしたい場合はEXACT計算を、それが日を近似しているため、その後、DATEDIFFはなど、@ShailendraMishraそれを行うことはありません。たとえば、select datediff(year, '2000-01-05', '2018-01-04')本来の17ではなく18を返します。私は「INTでの年のベストメソッド」という見出しの下で上記の例を使用しましたが、それは完全に機能します。ありがとう!
openwonk 2018年

132

お奨めはこれをそこに捨てます。あなたがいる場合の変換数に112スタイル(YYYYMMDD)を使用して日付をあなたはこのような計算を使用することができます...

(yyyyMMdd-yyyyMMdd)/ 10000 =通年の差

declare @as_of datetime, @bday datetime;
select @as_of = '2009/10/15', @bday = '1980/4/20'

select 
    Convert(Char(8),@as_of,112),
    Convert(Char(8),@bday,112),
    0 + Convert(Char(8),@as_of,112) - Convert(Char(8),@bday,112), 
    (0 + Convert(Char(8),@as_of,112) - Convert(Char(8),@bday,112)) / 10000

出力

20091015    19800420    290595  29

14
これは、うるう年の問題をすべて解決する方法において、ほとんど魔法のようです。112は、日付をyyyymmddにフォーマットするCONVERT関数の特別な数値であることは注目に値します。あなたがそれを見るとき、それはおそらく誰にとっても明白ではありません。
Derek Tomes、2015年

5
あなたは天才です!
ercan

私たちのチームは、年齢を見つけるために使用していた日付が、比較する日付と同じ日であるときに問題に直面していました。彼らが同じ日になると(そして年齢が奇数になると)、年齢が1つずれることに気づきました。これは完璧に機能しました!
Sheek Geek

1
これが正解です。そのようにマークしてください。
Snympi 2018

4
SQL Server 2012+でのこのまったく同じ計算方法の最も単純な/最短のコードはcode: SELECT [Age] = (0+ FORMAT(@as_of,'yyyyMMdd') - FORMAT(@bday,'yyyyMMdd') ) /10000 --The 0+ part tells SQL to calc the char(8) as numbers
ukgav

44

このクエリは、約10年間、製品コードで使用しています。

SELECT FLOOR((CAST (GetDate() AS INTEGER) - CAST(Date_of_birth AS INTEGER)) / 365.25) AS Age

6
悪くはありませんが、100%ではありません。2007/ 10/16は2009/10/15に2歳を報告します
Andrew

4
Doh、私たちは明白なものを欠いています、それは正午の後です、getdateはintを返すので、もちろん切り上げます。私はあなたの答えをコピーして貼り付けて実行したので、リテラルではなく自動的に使用されたgetdateを使用しました。
アンドリュー

2
エレガントでシンプル。ありがとう!
ウィリアムMB

9
人間の年齢について話している場合は、人間が年齢を計算する方法で計算する必要があります。地球の動きの速さや、カレンダーとの関係は一切関係ありません。たび誕生日と同じ月と日が経過し、1だけあなたがインクリメント年齢平均人間が何もミラーが、彼らは「年齢」と言うときので、次は最も正確である。この手段:DATEDIFF(yy, @BirthDate, GETDATE()) - CASE WHEN (MONTH(@BirthDate) >= MONTH(GETDATE())) AND DAY(@BirthDate) > DAY(GETDATE()) THEN 1 ELSE 0 END
ベーコンビット

5
その構文は間違っています。 CASE WHEN (MONTH(@date) > MONTH(GETDATE())) OR (MONTH(@date) = MONTH(GETDATE()) AND DAY(@date) > DAY(GETDATE())) THEN 1 ELSE 0 END
ベーコンビット2014年

31

したがって、上記のソリューションの多くは間違っています。DateDiff(yy、@ Dob、@PassedDate)は、両方の日付の月と日を考慮しません。また、ダーツのパーツを取り、比較すると、正しく注文された場合にのみ機能します。

次のコードは機能し、非常にシンプルです:

create function [dbo].[AgeAtDate](
    @DOB    datetime,
    @PassedDate datetime
)

returns int
with SCHEMABINDING
as
begin

declare @iMonthDayDob int
declare @iMonthDayPassedDate int


select @iMonthDayDob = CAST(datepart (mm,@DOB) * 100 + datepart  (dd,@DOB) AS int) 
select @iMonthDayPassedDate = CAST(datepart (mm,@PassedDate) * 100 + datepart  (dd,@PassedDate) AS int) 

return DateDiff(yy,@DOB, @PassedDate) 
- CASE WHEN @iMonthDayDob <= @iMonthDayPassedDate
  THEN 0 
  ELSE 1
  END

End

なぜ100倍するのですか?コードライブラリに存在するものをデータベースに複製しようとしているので、これは私にとってはうまくいきますが、あなたの機能を説明することはできませんでした。これは愚かな質問かもしれません:)
Jen

6
ありがとう!まさに私がここで期待していたコード。これは、(醜い)文字列変換なしのこのスレッドで唯一の正確なコードです!@Jen DoBの月と日(9月25日など)を取り、整数値0925(または925)に変換します。現在の日付と同じことを行い(12月16日がになるように1216)、DoB整数値が既に渡されているかどうかを確認します。この整数を作成するには、月が100で乗算されなければならない
bartlaarhoven

ありがとう@bartlaarhoven :)
Jen

これは文字列変換を回避しますが、代わりに多くのキャストを行うことを述べます。私のテストでは、それはdotjoeの回答よりも大幅に高速ではなく、コードはより冗長です。
StriplingWarrior 2018

受け入れ答えははるかに簡単INTの答えを持っている:(CONVERT(int,CONVERT(char(8),@Now,112))-CONVERT(char(8),@Dob,112))/10000
KM。

19

datediffコマンドの丸め方を考慮する必要があります。

SELECT CASE WHEN dateadd(year, datediff (year, DOB, getdate()), DOB) > getdate()
            THEN datediff(year, DOB, getdate()) - 1
            ELSE datediff(year, DOB, getdate())
       END as Age
FROM <table>

ここから採用し

2月28日をうるう年以外の年の跳躍の誕生日と見なすことに注意してください。たとえば、2020年2月29日に生まれた人は、2021年3月1日ではなく2021年2月28日に1歳と見なされます。


@Andrew-修正済み-代替の1つを見逃しました
Ed Harper、

1
簡略化されたバージョンSELECT DATEDIFF(year, DOB, getdate()) + CASE WHEN (DATEADD(year,DATEDIFF(year, DOB, getdate()) , DOB) > getdate()) THEN - 1 ELSE 0 END)
Peter

これは正しいアプローチです。なぜハックがそんなに賛成されているのか分かりません。
Salman A

8

編集:この回答は正しくありません。 私はここで、使用したい人への警告として残しdayofyear、最後にさらに編集を加えます。


私のように、端数の日数で除算したくない、または丸め/うるう年のエラーを危険にさらしたくない場合は、https://stackoverflow.com/a/1572257/489865の上の投稿にある@Bacon Bitsのコメントを称賛します。

人間の年齢について話している場合は、人間が年齢を計算する方法で計算する必要があります。地球の動きの速さや、カレンダーとの関係は一切関係ありません。生年月日と同じ月日が経過するたびに、年齢を1ずつ増分します。これは、人間が「年齢」と言うときの意味を反映しているため、以下が最も正確であることを意味します。

それから彼は提供します:

DATEDIFF(yy, @date, GETDATE()) -
CASE WHEN (MONTH(@date) > MONTH(GETDATE())) OR (MONTH(@date) = MONTH(GETDATE()) AND DAY(@date) > DAY(GETDATE()))
THEN 1 ELSE 0 END

月と日を比較することを含むいくつかの提案がここにあります(そしていくつかはそれを誤解し、ORここで正しく許可することに失敗します!)。しかし、誰も提供していませんdayofyear。これはとてもシンプルでずっと短いようです。私が提供しています:

DATEDIFF(year, @date, GETDATE()) -
CASE WHEN DATEPART(dayofyear, @date) > DATEPART(dayofyear, GETDATE()) THEN 1 ELSE 0 END

[注:SQL BOL / MSDNのどこにも、DATEPART(dayofyear, ...)実際に文書化されて返されるものはありません!1から366の範囲の数値であることを理解しています。最も重要なのは、&ごとにロケールによって変化しないことです。]DATEPART(weekday, ...)SET DATEFIRST


EDIT: なぜdayofyearうまくいかない:誕生/日が非うるう年で2月以降で起動した場合、ユーザー@AeroXは、コメントしたように、現在の/終了日は、うるう年で早いとき、年齢が1日インクリメントされ、例えば'2015-05-26''2016-05-25'ANができますまだ0であるはずの1歳dayofyear。異なる年のを比較することは明らかに危険です。結局のところMONTH()、とを使用するDAY()必要があります。


これは投票するか、回答としてマークする必要があります。それは短く、エレガントで、論理的に正しいです。
z00l 2016年

1
2月以降に生まれたすべての人の年齢は、このDayOfYear方法を使用して、うるう年ごとに1日早く増分されます。
AeroX 2016年

4
@AeroXこの欠陥を見つけていただきありがとうございます。私は自分の解決策を、を使用した可能性のある人や使用したことのある人への警告として残すことにしましたが、dayofyearそれがうまくいかない理由を示すために明確に編集しました。それが適切だと思います。
JonBrave 2016年

5

常に正しい年齢を示す簡単な答えは1つもないので、ここに私が思いついたものがあります。

SELECT DATEDIFF(YY, DateOfBirth, GETDATE()) - 
     CASE WHEN RIGHT(CONVERT(VARCHAR(6), GETDATE(), 12), 4) >= 
               RIGHT(CONVERT(VARCHAR(6), DateOfBirth, 12), 4) 
     THEN 0 ELSE 1 END AS AGE 

これにより、誕生日と現在の日付の年の差が取得されます。次に、生年月日がまだ経過していない場合は1年を減算します。

うるう年や誕生日に関係なく、常に正確です。

すべてのベスト-機能なし。


3
SELECT ID,
Name,
DATEDIFF(yy,CONVERT(DATETIME, DOB),GETDATE()) AS AGE,
DOB
FROM MyTable

1
最初の引数ではなく2番目の引数としてgetdateを使用したい場合は、負の数値の結果とdatediffの丸めが得られるため、datediff(yy、 '20081231'、getdate())を選択すると、1歳が報告されますが、10か月しか経過しません。 。
Andrew

1
この計算では、今年の誕生日がまだない人の計算は正しくありません。

3

何について:

DECLARE @DOB datetime
SET @DOB='19851125'   
SELECT Datepart(yy,convert(date,GETDATE())-@DOB)-1900

これにより、丸め、切り捨て、および相殺の問題がすべて回避されませんか?


あなたの計算は正確ではありません。たとえば'1986-07-05 00:00:00'、DOBと'2013-07-04 23:59:59'現在の時刻を取得すると失敗します。
drinovc 2016年

@ub_coding提供して回答したり、別の質問をしたりしていますか?
アーロンC

これ:DECLARE @DOB datetime SET @ DOB = '19760229' SELECT Datepart(yy、convert(datetime、 '19770228')-@ DOB)-1900 = 1主な問題は、ほとんどのソリューションの2月29日のギャップです。 。
レオナルド・マルケス・デ・ソウザ

3

これはここに掲載されている他のソリューションと似ていると思いますが、この解決策はうるう年の例02/29/1976から03/01/2011まで機能し、初年度のケースでも機能しました。 / 2011から2012年7月3日まで、うるう年ソリューションについて最後に投稿したものは、その最初の年のユースケースでは機能しませんでした。

SELECT FLOOR(DATEDIFF(DAY, @date1 , @date2) / 365.25)

ここで見つかりまし


3

以下の答えが実行可能かどうかを確認してください。

DECLARE @BirthDate DATE = '09/06/1979'

SELECT 
 (
 YEAR(GETDATE()) - YEAR(@BirthDate) - 
 CASE  WHEN (MONTH(GETDATE()) * 100) + DATEPART(dd, GETDATE()) >     
 (MONTH(@BirthDate) * 100) + DATEPART(dd, @BirthDate)
 THEN 1             
 ELSE 0             
 END        
 )

2
DECLARE @DOB datetime
set @DOB ='11/25/1985'

select floor(
( cast(convert(varchar(8),getdate(),112) as int)-
cast(convert(varchar(8),@DOB,112) as int) ) / 10000
)

ソース:http : //beginsql.wordpress.com/2012/04/26/how-to-calculate-age-in-sql-server/


SQL Serverの2012+でこれを行うための簡単な方法は、次のようになり、112に変換を回避し、床が必要とされていません:code: SELECT [Age] = (0+ FORMAT(@ToDate,'yyyyMMdd') - FORMAT(@DOB,'yyyyMMdd') ) /10000
ukgav

2

私はこれについて多くの考えや検索を行ってきましたが、3つの解決策があります。

  • 年齢を正しく計算する
  • 短い(ほとんど)
  • (ほとんど)非常に理解可能です。

テスト値は次のとおりです。

DECLARE @NOW DATETIME = '2013-07-04 23:59:59' 
DECLARE @DOB DATETIME = '1986-07-05' 

解決策1:私はこのアプローチを1つのjsライブラリで見つけました。それは私のお気に入りです。

DATEDIFF(YY, @DOB, @NOW) - 
  CASE WHEN DATEADD(YY, DATEDIFF(YY, @DOB, @NOW), @DOB) > @NOW THEN 1 ELSE 0 END

実際には、DOBに年数の差が追加されており、現在の日付よりも大きい場合は1年差し引かれます。シンプルでしょ?唯一のことは、年の違いがここで複製されることです。

ただし、インラインで使用する必要がない場合は、次のように記述できます。

DECLARE @AGE INT = DATEDIFF(YY, @DOB, @NOW)
IF DATEADD(YY, @AGE, @DOB) > @NOW
SET @AGE = @AGE - 1

解決策2:これはもともと@ bacon-bitsからコピーしたものです。それは理解するのが最も簡単ですが、少し長いです。

DATEDIFF(YY, @DOB, @NOW) - 
  CASE WHEN MONTH(@DOB) > MONTH(@NOW) 
    OR MONTH(@DOB) = MONTH(@NOW) AND DAY(@DOB) > DAY(@NOW) 
  THEN 1 ELSE 0 END

基本的には、人間と同じように年齢を計算しています。


解決策3:私の友人はそれをこれにリファクタリングしました:

DATEDIFF(YY, @DOB, @NOW) - 
  CEILING(0.5 * SIGN((MONTH(@DOB) - MONTH(@NOW)) * 50 + DAY(@DOB) - DAY(@NOW)))

これは最短ですが、理解するのが最も難しいです。50は単なる重みなので、日差は月が同じ場合にのみ重要です。SIGN関数は、-1、0、または1に取得する値を変換するためのものです。SQL CEILING(0.5 *と同じですが、Math.max(0, value)そのようなものはありません。


1
CASE WHEN datepart(MM, getdate()) < datepart(MM, BIRTHDATE) THEN ((datepart(YYYY, getdate()) - datepart(YYYY, BIRTH_DATE)) -1 )
     ELSE 
        CASE WHEN datepart(MM, getdate()) = datepart(MM, BIRTHDATE)
            THEN 
                CASE WHEN datepart(DD, getdate()) < datepart(DD, BIRTHDATE) THEN ((datepart(YYYY, getdate()) - datepart(YYYY, BIRTHDATE)) -1 )
                    ELSE (datepart(YYYY, getdate()) - datepart(YYYY, BIRTHDATE))
                END
        ELSE (datepart(YYYY, getdate()) - datepart(YYYY, BIRTHDATE)) END            
    END

1
select floor((datediff(day,0,@today) - datediff(day,0,@birthdate)) / 365.2425) as age

ここには365.25の答えがたくさんあります。うるう年の定義方法を覚えておいてください。

  • 四年ごと
    • 100年ごとを除い
      • 400年ごとを除い

すばらしい答えです。ここに興味がある人のため365.2425が使用する正しい値である理由の説明は次のとおりです。grc.nasa.gov/WWW/k-12/Numbers/Math/Mathematical_Thinking/...
vvvv4d

0

これはどう:

SET @Age = CAST(DATEDIFF(Year, @DOB, @Stamp) as int)
IF (CAST(DATEDIFF(DAY, DATEADD(Year, @Age, @DOB), @Stamp) as int) < 0) 
    SET @Age = @Age - 1

0

これを試して

DECLARE @date datetime, @tmpdate datetime, @years int, @months int, @days int
SELECT @date = '08/16/84'

SELECT @tmpdate = @date

SELECT @years = DATEDIFF(yy, @tmpdate, GETDATE()) - CASE WHEN (MONTH(@date) > MONTH(GETDATE())) OR (MONTH(@date) = MONTH(GETDATE()) AND DAY(@date) > DAY(GETDATE())) THEN 1 ELSE 0 END
SELECT @tmpdate = DATEADD(yy, @years, @tmpdate)
SELECT @months = DATEDIFF(m, @tmpdate, GETDATE()) - CASE WHEN DAY(@date) > DAY(GETDATE()) THEN 1 ELSE 0 END
SELECT @tmpdate = DATEADD(m, @months, @tmpdate)
SELECT @days = DATEDIFF(d, @tmpdate, GETDATE())

SELECT Convert(Varchar(Max),@years)+' Years '+ Convert(Varchar(max),@months) + ' Months '+Convert(Varchar(Max), @days)+'days'

0

この解決策を試してください:

declare @BirthDate datetime
declare @ToDate datetime

set @BirthDate = '1/3/1990'
set @ToDate = '1/2/2008'
select @BirthDate [Date of Birth], @ToDate [ToDate],(case when (DatePart(mm,@ToDate) <  Datepart(mm,@BirthDate)) 
        OR (DatePart(m,@ToDate) = Datepart(m,@BirthDate) AND DatePart(dd,@ToDate) < Datepart(dd,@BirthDate))
        then (Datepart(yy, @ToDate) - Datepart(yy, @BirthDate) - 1)
        else (Datepart(yy, @ToDate) - Datepart(yy, @BirthDate))end) Age

0

これにより、誕生日と丸めに関する問題が正しく処理されます。

DECLARE @dob  datetime
SET @dob='1992-01-09 00:00:00'

SELECT DATEDIFF(YEAR, '0:0', getdate()-@dob)

2
うるう年を正しく処理しないSELECT DATEDIFF(YEAR、 '0:0'、convert(datetime、 '2014-02-28')-'2012-02-29 ')は2を返しますが、1のみでなければなりません
Peter Kerr

0

Ed Harperの解決策は、2つの日付の月と日が1日以内離れているときに間違った答えを返さないことがわかった最も簡単なものです。ネガティブな年齢に対応するために少し変更を加えました。

DECLARE @D1 AS DATETIME, @D2 AS DATETIME
SET @D2 = '2012-03-01 10:00:02'
SET @D1 = '2013-03-01 10:00:01'
SELECT
   DATEDIFF(YEAR, @D1,@D2)
   +
   CASE
      WHEN @D1<@D2 AND DATEADD(YEAR, DATEDIFF(YEAR,@D1, @D2), @D1) > @D2
      THEN - 1
      WHEN @D1>@D2 AND DATEADD(YEAR, DATEDIFF(YEAR,@D1, @D2), @D1) < @D2
      THEN 1
      ELSE 0
   END AS AGE

0

正しいとマークされた答えは正確に近いですが、次のシナリオでは失敗します- 誕生年はうるう年であり、日は2月より後です

declare @ReportStartDate datetime = CONVERT(datetime, '1/1/2014'),
@DateofBirth datetime = CONVERT(datetime, '2/29/1948')

FLOOR(DATEDIFF(HOUR,@DateofBirth,@ReportStartDate )/8766)


または

FLOOR(DATEDIFF(HOUR,@DateofBirth,@ReportStartDate )/8765.82) -- Divisor is more accurate than 8766

-以下の解決策により、より正確な結果が得られます。

FLOOR(DATEDIFF(YEAR,@DateofBirth,@ReportStartDate) - (CASE WHEN DATEADD(YY,DATEDIFF(YEAR,@DateofBirth,@ReportStartDate),@DateofBirth) > @ReportStartDate THEN 1 ELSE 0 END ))

うるう年、2月29日など、ほとんどすべてのシナリオで機能しました。

この式に抜け穴がある場合は修正してください。


最終的な式は、この回答とほぼ同じです。stackoverflow.com/a/1572235/168747。しかし、ここでは読みにくく、不要なものが含まれていますfloor
Marek

0
Declare @dob datetime
Declare @today datetime

Set @dob = '05/20/2000'
set @today = getdate()

select  CASE
            WHEN dateadd(year, datediff (year, @dob, @today), @dob) > @today 
            THEN datediff (year, @dob, @today) - 1
            ELSE datediff (year, @dob, @today)
        END as Age

0

これは、誕生日と現在の日付を指定して年齢を計算する方法です。

select case 
            when cast(getdate() as date) = cast(dateadd(year, (datediff(year, '1996-09-09', getdate())), '1996-09-09') as date)
                then dateDiff(yyyy,'1996-09-09',dateadd(year, 0, getdate()))
            else dateDiff(yyyy,'1996-09-09',dateadd(year, -1, getdate()))
        end as MemberAge
go

0
CREATE function dbo.AgeAtDate(
    @DOB    datetime,
    @CompareDate datetime
)

returns INT
as
begin

return CASE WHEN @DOB is null
THEN 
    null
ELSE 
DateDiff(yy,@DOB, @CompareDate) 
- CASE WHEN datepart(mm,@CompareDate) > datepart(mm,@DOB) OR (datepart(mm,@CompareDate) = datepart(mm,@DOB) AND datepart(dd,@CompareDate) >= datepart(dd,@DOB))
  THEN 0 
  ELSE 1
  END
END
End

GO

-1:間違っている任意の時間になりますmonth(compare) > month(dob)しかしday(compare) < day(dob)、例えばselect dbo.AgeAtDate('2000-01-14', '2016-02-12')
JonBrave 2016

あなたは正しい、この場合はありがとう、機能を更新しました
Vova

0
DECLARE @FromDate DATETIME = '1992-01-2623:59:59.000', 
        @ToDate   DATETIME = '2016-08-10 00:00:00.000',
        @Years INT, @Months INT, @Days INT, @tmpFromDate DATETIME
SET @Years = DATEDIFF(YEAR, @FromDate, @ToDate)
 - (CASE WHEN DATEADD(YEAR, DATEDIFF(YEAR, @FromDate, @ToDate),
          @FromDate) > @ToDate THEN 1 ELSE 0 END) 


SET @tmpFromDate = DATEADD(YEAR, @Years , @FromDate)
SET @Months =  DATEDIFF(MONTH, @tmpFromDate, @ToDate)
 - (CASE WHEN DATEADD(MONTH,DATEDIFF(MONTH, @tmpFromDate, @ToDate),
          @tmpFromDate) > @ToDate THEN 1 ELSE 0 END) 

SET @tmpFromDate = DATEADD(MONTH, @Months , @tmpFromDate)
SET @Days =  DATEDIFF(DAY, @tmpFromDate, @ToDate)
 - (CASE WHEN DATEADD(DAY, DATEDIFF(DAY, @tmpFromDate, @ToDate),
          @tmpFromDate) > @ToDate THEN 1 ELSE 0 END) 

SELECT @FromDate FromDate, @ToDate ToDate, 
       @Years Years,  @Months Months, @Days Days

0

うるう年を心配せず、数学関数ではなく日付関数のみのソリューションについてはどうですか

CREATE FUNCTION dbo.getAge(@dt datetime) 
RETURNS int
AS
BEGIN
    RETURN 
        DATEDIFF(yy, @dt, getdate())
        - CASE 
            WHEN 
                MONTH(@dt) > MONTH(GETDATE()) OR 
                (MONTH(@dt) = MONTH(GETDATE()) AND DAY(@dt) > DAY(GETDATE())) 
            THEN 1 
            ELSE 0 
        END
END

0

MANYメソッドを試した後、これはスタイル112に変換する代わりに最新のMS SQL FORMAT関数を使用して100%機能します。どちらでも機能しますが、これは最もコードが少ないコードです。

誰かが機能しない日付の組み合わせを見つけることができますか?私は1つはないと思います:)

--Set parameters, or choose from table.column instead:

DECLARE @DOB    DATE = '2000/02/29' -- If @DOB is a leap day...
       ,@ToDate DATE = '2018/03/01' --...there birthday in this calculation will be 

--0+ part tells SQL to calc the char(8) as numbers:
SELECT [Age] = (0+ FORMAT(@ToDate,'yyyyMMdd') - FORMAT(@DOB,'yyyyMMdd') ) /10000

-2

私たちはここのようなものを使用しましたが、その後平均年齢を取ります:

ROUND(avg(CONVERT(int,DATEDIFF(hour,DOB,GETDATE())/8766.0)),0) AS AverageAge

ROUNDは内側ではなく外側にあることに注意してください。これにより、AVGがより正確になり、ROUNDが1回だけ行われます。それも速くする。


-2
select DATEDIFF(yy,@DATE,GETDATE()) -
case when DATEPART(mm,GETDATE())*100+DATEPART(dd,GETDATE())>=
DATEPART(mm,@DATE)*100+DATEPART(dd,@DATE) THEN 0
ELSE 1 END 

-2
SELECT CAST(DATEDIFF(dy, @DOB, GETDATE()+1)/365.25 AS int)

私は反対票を見ていますが、これが破綻していることを証明する例は見ていません。
Alex
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.