スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

MySQLでDate関数同士を比較するときの注意

MySQLには日付の計算を行う関数がいくつかあって、例えば当日は


mysql> SELECT NOW();
+---------------------+
| NOW() |
+---------------------+
| 2012-04-23 16:26:11 |
+---------------------+
1 row in set (0.00 sec)



前日は

mysql> SELECT NOW() - interval 1 day;
+------------------------+
| NOW() - interval 1 day |
+------------------------+
| 2012-04-22 16:28:17 |
+------------------------+
1 row in set (0.00 sec)



で、これを日付だけ取り出したい場合、Date()を使う

mysql> SELECT date(NOW() - interval 1 day);
+------------------------------+
| date(NOW() - interval 1 day) |
+------------------------------+
| 2012-04-22 |
+------------------------------+
1 row in set (0.00 sec)



単体で動かしているならこれで問題ないんだけど、Date()同士の引き算の結果がおかしくて軽くハマったので備忘録
まず同一月の引き算

mysql> SELECT DATE(NOW());
+-------------+
| DATE(NOW()) |
+-------------+
| 2012-04-23 |
+-------------+
1 row in set (0.00 sec);

mysql> SELECT DATE(NOW() - INTERVAL 1 DAY);
+------------------------------+
| DATE(NOW() - INTERVAL 1 DAY) |
+------------------------------+
| 2012-04-22 |
+------------------------------+
1 row in set (0.00 sec);

mysql> SELECT DATE(NOW()) - DATE(NOW() - INTERVAL 1 DAY);
+--------------------------------------------+
| DATE(NOW()) - DATE(NOW() - INTERVAL 1 DAY) |
+--------------------------------------------+
| 1 |
+--------------------------------------------+
1 row in set (0.00 sec)



同月同士なら全く問題なく計算できる。これが月をまたぐと全くおかしくなる。

mysql> SELECT DATE(NOW());
+-------------+
| DATE(NOW()) |
+-------------+
| 2012-04-23 |
+-------------+
1 row in set (0.00 sec)

mysql> SELECT DATE(NOW() - INTERVAL 23 DAY);
+-------------------------------+
| DATE(NOW() - INTERVAL 23 DAY) |
+-------------------------------+
| 2012-03-31 |
+-------------------------------+
1 row in set (0.00 sec)

mysql> SELECT DATE(NOW()) - DATE(NOW() - INTERVAL 23 DAY);
+---------------------------------------------+
| DATE(NOW()) - DATE(NOW() - INTERVAL 23 DAY) |
+---------------------------------------------+
| 92 |
+---------------------------------------------+
1 row in set (0.01 sec)


!?

どうも日付同士の演算をする場合、Date()だと年を365日、月を30 or 31 or 29として計算し直すのではなく、単純に年、月を10進数で+1桁としているようだ。
だからひと月前は30日ではなく、100、年は1000が足されたような格好になる。

なので日付どうしの計算を行う場合は、ちゃんとTO_DAYSを使いましょう。


mysql> SELECT TO_DAYS(NOW()) - TO_DAYS(NOW() - INTERVAL 23 DAY);
+---------------------------------------------------+
| TO_DAYS(NOW()) - TO_DAYS(NOW() - INTERVAL 23 DAY) |
+---------------------------------------------------+
| 23 |
+---------------------------------------------------+
1 row in set (0.00 sec)



もしくはDATEDIFF

mysql> SELECT DATEDIFF(DATE(NOW()), DATE(NOW() - INTERVAL 23 DAY));
+------------------------------------------------------+
| DATEDIFF(DATE(NOW()), DATE(NOW() - INTERVAL 23 DAY)) |
+------------------------------------------------------+
| 23 |
+------------------------------------------------------+
1 row in set (0.00 sec)



使用頻度はどっちが高いんだろう。
スポンサーサイト

Leave a reply






管理者にだけ表示を許可する

該当の記事は見つかりませんでした。
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。