年齢の計算

自分って何歳だっけ？って事がたま～にあるので、
そんな時に使ってる、年齢を求めるSQLを記載します。

```sql
SELECT TRUNC(MONTHS_BETWEEN(SYSDATE, TO_DATE(生年月日, 'yyyymmdd')) / 12) FROM DUAL
```

しかし、この方法だと閏年生まれな人の年齢がズレてました。
（例）**1996年2月29日生まれな人の年齢**を表示します。


```sql
SELECT
  TRUNC(MONTHS_BETWEEN(TO_DATE('1997/02/27', 'yyyy/mm/dd'), TO_DATE('1996/02/29', 'yyyy/mm/dd')) / 12) AS "1997/02/27",
  TRUNC(MONTHS_BETWEEN(TO_DATE('1997/02/28', 'yyyy/mm/dd'), TO_DATE('1996/02/29', 'yyyy/mm/dd')) / 12) AS "1997/02/28",
  TRUNC(MONTHS_BETWEEN(TO_DATE('1997/03/01', 'yyyy/mm/dd'), TO_DATE('1996/02/29', 'yyyy/mm/dd')) / 12) AS "1997/03/01",
  TRUNC(MONTHS_BETWEEN(TO_DATE('2000/02/27', 'yyyy/mm/dd'), TO_DATE('1996/02/29', 'yyyy/mm/dd')) / 12) AS "2000/02/27",
  TRUNC(MONTHS_BETWEEN(TO_DATE('2000/02/28', 'yyyy/mm/dd'), TO_DATE('1996/02/29', 'yyyy/mm/dd')) / 12) AS "2000/02/28",
  TRUNC(MONTHS_BETWEEN(TO_DATE('2000/02/29', 'yyyy/mm/dd'), TO_DATE('1996/02/29', 'yyyy/mm/dd')) / 12) AS "2000/02/29",
  TRUNC(MONTHS_BETWEEN(TO_DATE('2000/03/01', 'yyyy/mm/dd'), TO_DATE('1996/02/29', 'yyyy/mm/dd')) / 12) AS "2000/03/01"
FROM DUAL
```

- 実行結果

|1997/02/27|1997/02/28|1997/03/01|2000/02/27|2000/02/28|2000/02/29|2000/03/01|
|:---------|:---------|:---------|:---------|:---------|:---------|:---------|
|0         |1         |1         |3         |3         |4         |4         |

**1996年2月29日生まれな人は**
1997年2月27日の時点では「0」で、1997年2月28日に「1」となりました。
しかし、2000年2月28日の時点では「3」で、2000年2月29日に「4」となっています。
1997年2月28日の時点では「0」になって欲しかったのですが、想定と違う結果になっていました。

想定通りに年齢を取得出来る方法が無いか調べてみたところ、下記のような記述でも年齢を取得できるようです。

```sql
SELECT TRUNC((TO_CHAR(SYSDATE, 'YYYYMMDD') - YYYYMMDD形式の生年月日) / 10000) FROM DUAL
```

このSQLを用いて、前述と同じ**1996年2月29日生まれな人の年齢**を表示させてみると

```sql
SELECT 
TRUNC((TO_CHAR(TO_DATE('1997/02/27', 'YYYY/MM/DD'), 'YYYYMMDD') - TO_CHAR(TO_DATE('1996/02/29', 'YYYY/MM/DD'), 'YYYYMMDD'))/10000) AS "1997/02/27",
TRUNC((TO_CHAR(TO_DATE('1997/02/28', 'YYYY/MM/DD'), 'YYYYMMDD') - TO_CHAR(TO_DATE('1996/02/29', 'YYYY/MM/DD'), 'YYYYMMDD'))/10000) AS "1997/02/28",
TRUNC((TO_CHAR(TO_DATE('1997/03/01', 'YYYY/MM/DD'), 'YYYYMMDD') - TO_CHAR(TO_DATE('1996/02/29', 'YYYY/MM/DD'), 'YYYYMMDD'))/10000) AS "1997/03/01",
TRUNC((TO_CHAR(TO_DATE('2000/02/27', 'YYYY/MM/DD'), 'YYYYMMDD') - TO_CHAR(TO_DATE('1996/02/29', 'YYYY/MM/DD'), 'YYYYMMDD'))/10000) AS "2000/02/27",
TRUNC((TO_CHAR(TO_DATE('2000/02/28', 'YYYY/MM/DD'), 'YYYYMMDD') - TO_CHAR(TO_DATE('1996/02/29', 'YYYY/MM/DD'), 'YYYYMMDD'))/10000) AS "2000/02/28",
TRUNC((TO_CHAR(TO_DATE('2000/02/29', 'YYYY/MM/DD'), 'YYYYMMDD') - TO_CHAR(TO_DATE('1996/02/29', 'YYYY/MM/DD'), 'YYYYMMDD'))/10000) AS "2000/02/29",
TRUNC((TO_CHAR(TO_DATE('2000/03/01', 'YYYY/MM/DD'), 'YYYYMMDD') - TO_CHAR(TO_DATE('1996/02/29', 'YYYY/MM/DD'), 'YYYYMMDD'))/10000) AS "2000/03/01"
FROM DUAL;
```

- 実行結果

|1997/02/27|1997/02/28|1997/03/01|2000/02/27|2000/02/28|2000/02/29|2000/03/01|
|:---------|:---------|:---------|:---------|:---------|:---------|:---------|
|0         |0         |1         |3         |3         |4         |4         |

**1996年2月29日生まれな人は**
1997年2月28日の時点では「0」で、1997年3月1日に「1」になりました。
2000年2月28日の時点では「3」で、2000年2月29日に「4」となり、望んでいた結果が返ってきました。

年月日を8桁の数字にして、差を求めてから10000で割って端数を切り捨てると、年数だけを取得できるようです。
年齢を算出する数式と証明を記載している記事があったので、参考に記載しておきます。

参考リンクの記事にも記載がありましたが、業務で使用する場合、用途に沿った方法で年齢を算出する必要があります。

- 参考

[生年月日から年齢を簡易計算するコード](https://qiita.com/AQRiL_1132/items/46e824541e657190ef3e)