MySQL では、年齢計算や日付の一部の抽出など、日付計算を実行するためのさまざまな関数が用意されています。
それぞれのペットの年齢を取得するには、現在の日付と誕生日の年の部分の差を求め、現在の日付の月日の部分が誕生日の月日の部分よりも暦年で早い場合は、さらにそこから 1 を引くという計算をします。以下のクエリは、それぞれのペットについて、誕生日、現在の日付、および年齢を返します。
mysql>SELECT name, birth, CURDATE(),
->(YEAR(CURDATE())-YEAR(birth))
->- (RIGHT(CURDATE(),5)<RIGHT(birth,5))
->AS age
->FROM pet;
+----------+------------+------------+------+ | name | birth | CURDATE() | age | +----------+------------+------------+------+ | Fluffy | 1993-02-04 | 2003-08-19 | 10 | | Claws | 1994-03-17 | 2003-08-19 | 9 | | Buffy | 1989-05-13 | 2003-08-19 | 14 | | Fang | 1990-08-27 | 2003-08-19 | 12 | | Bowser | 1989-08-31 | 2003-08-19 | 13 | | Chirpy | 1998-09-11 | 2003-08-19 | 4 | | Whistler | 1997-12-09 | 2003-08-19 | 5 | | Slim | 1996-04-29 | 2003-08-19 | 7 | | Puffball | 1999-03-30 | 2003-08-19 | 4 | +----------+------------+------------+------+
ここで、YEAR()
は日付の年の部分を抽出します。RIGHT()
は日付の
MM-DD
(暦年)を表す右端の 5
文字を抽出します。MM-DD
の値を比較する式は 1 または 0
に評価され、それによって
CURDATE()
が birth
よりも暦年で早いと判断される場合は、年の差からさらに
1
を引きます。出力するカラムのラベルは、式全体だと長すぎるので、エイリアス(age
)を使用して、わかりやすくします。
このままでもクエリは動作しますが、結果を何らかの順序でソートすれば、その内容を調べやすくなります。それには、ORDER
BY name
節を追加して、名前でソートした結果を出力します。
mysql>SELECT name, birth, CURDATE(),
->(YEAR(CURDATE())-YEAR(birth))
->- (RIGHT(CURDATE(),5)<RIGHT(birth,5))
->AS age
->FROM pet ORDER BY name;
+----------+------------+------------+------+ | name | birth | CURDATE() | age | +----------+------------+------------+------+ | Bowser | 1989-08-31 | 2003-08-19 | 13 | | Buffy | 1989-05-13 | 2003-08-19 | 14 | | Chirpy | 1998-09-11 | 2003-08-19 | 4 | | Claws | 1994-03-17 | 2003-08-19 | 9 | | Fang | 1990-08-27 | 2003-08-19 | 12 | | Fluffy | 1993-02-04 | 2003-08-19 | 10 | | Puffball | 1999-03-30 | 2003-08-19 | 4 | | Slim | 1996-04-29 | 2003-08-19 | 7 | | Whistler | 1997-12-09 | 2003-08-19 | 5 | +----------+------------+------------+------+
name
ではなく、age
を使用して出力をソートするには、別の
ORDER BY
節を使用します。
mysql>SELECT name, birth, CURDATE(),
->(YEAR(CURDATE())-YEAR(birth))
->- (RIGHT(CURDATE(),5)<RIGHT(birth,5))
->AS age
->FROM pet ORDER BY age;
+----------+------------+------------+------+ | name | birth | CURDATE() | age | +----------+------------+------------+------+ | Chirpy | 1998-09-11 | 2003-08-19 | 4 | | Puffball | 1999-03-30 | 2003-08-19 | 4 | | Whistler | 1997-12-09 | 2003-08-19 | 5 | | Slim | 1996-04-29 | 2003-08-19 | 7 | | Claws | 1994-03-17 | 2003-08-19 | 9 | | Fluffy | 1993-02-04 | 2003-08-19 | 10 | | Fang | 1990-08-27 | 2003-08-19 | 12 | | Bowser | 1989-08-31 | 2003-08-19 | 13 | | Buffy | 1989-05-13 | 2003-08-19 | 14 | +----------+------------+------------+------+
同じようなクエリを使用して、死んだペットの死亡時の年齢を取得できます。死んだペットかどうかは、death
カラムの値が NULL
かどうかを調べて判断します。それが
NULL
以外の値であるペットについて、death
カラムと birth
カラムの値の差を計算します。
mysql>SELECT name, birth, death,
->(YEAR(death)-YEAR(birth)) - (RIGHT(death,5)<RIGHT(birth,5))
->AS age
->FROM pet WHERE death IS NOT NULL ORDER BY age;
+--------+------------+------------+------+ | name | birth | death | age | +--------+------------+------------+------+ | Bowser | 1989-08-31 | 1995-07-29 | 5 | +--------+------------+------------+------+
このクエリでは、death <> NULL
ではなく、death IS NOT NULL
を使用しています。これは、NULL
が特別な値であり、通常の比較演算子を使用して比較することができないためです。これについては、後で説明します。
See 項3.3.4.6. 「NULL
値の使用」。
来月に誕生日を迎えるペットを取得する場合はどうすればよいでしょうか。この場合の計算では、年と日の部分は必要なく、birth
カラムの月の部分だけを抽出する必要があります。MySQL
では、YEAR()
、MONTH()
、および
DAYOFMONTH()
など、日付の一部を抽出する関数が用意されています。ここでは、MONTH()
が適しています。その動作を調べるには、birth
および MONTH(birth)
の両方の値を表示する簡単なクエリを実行します。
mysql> SELECT name, birth, MONTH(birth) FROM pet;
+----------+------------+--------------+
| name | birth | MONTH(birth) |
+----------+------------+--------------+
| Fluffy | 1993-02-04 | 2 |
| Claws | 1994-03-17 | 3 |
| Buffy | 1989-05-13 | 5 |
| Fang | 1990-08-27 | 8 |
| Bowser | 1989-08-31 | 8 |
| Chirpy | 1998-09-11 | 9 |
| Whistler | 1997-12-09 | 12 |
| Slim | 1996-04-29 | 4 |
| Puffball | 1999-03-30 | 3 |
+----------+------------+--------------+
来月に誕生日を迎えるペットも、同じように簡単に取得できます。現在が
4 月であるとします。その場合、月の値は
4
であり、以下のように指定して、5
月(5
)に生まれたペットを取得します。
mysql> SELECT name, birth FROM pet WHERE MONTH(birth) = 5;
+-------+------------+
| name | birth |
+-------+------------+
| Buffy | 1989-05-13 |
+-------+------------+
現在が 12 月の場合は多少複雑になります。12
月(12
)に単純に 1
を足して翌月(13
)に生まれたペットを取得しようとしても、そのような月は存在しないので成功しません。この場合は
1
月(1
)に生まれたペットを取得する必要があります。
現在がどの月であっても動作するクエリを作成することもできます。この場合、クエリで特定の月数を指定する必要はありません。DATE_ADD()
を使用すると、指定された日付に期間を加算できます。CURDATE()
の値に 1 ヵ月を加算し、その結果から
MONTH()
を使用して月の部分を抽出すると、ペットの誕生日を調べる月がわかります。
mysql>SELECT name, birth FROM pet
->WHERE MONTH(birth) = MONTH(DATE_ADD(CURDATE(), INTERVAL 1 MONTH));
現在の月(剰余関数(MOD
)を使用して現在が
12
月の場合は 0
にする)に 1
を加算する方法でも同じ結果が得られます。
mysql>SELECT name, birth FROM pet
->WHERE MONTH(birth) = MOD(MONTH(CURDATE()), 12) + 1;
注意: MONTH
は 1
から 12
の範囲の値を返します。また、MOD(something,12)
は 0
から 11
の範囲の値を返します。したがって、加算する前に
MOD()
を実行する必要があります。そうしないと、11
月(11
)の次が 1
月(1
)になります。
This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.