MySQL で年月(yyyy/mm)のデータ型と PERIOD_ADD/DIFF

いわゆる請求データみたいなやつで請求年月のような yyyy/mm の値を表すために DATE 側を使うか整数型で yyyymm みたいにするか。

DATE 型で日付を 1 固定で持っていたとして、例えば請求年月が 2018/01 という条件で検索するとき 請求年月 = 2018/01/01 だと意味的におかしい気がする、請求年月 between 2018/01/01 and 2018/01/31 でなければならない。

そういう余計なことを考えなくていいようにするために yyyymm 形式の整数で持っておいて 請求年月 = 201801 とするのはアリだと思います。

ただ、例えば期間のデータで日割りが必要がないので yyyy/mm ~ yyyy/mm のように年月だけで持たせておくと、日付計算することも考えると整数型だと都合が悪いです。DATE型で持っていたほうが DATE_ADD とかがそのまま使えて便利です。

ただ、その場合 2018/01/01 ~ 2018/03/01 などとなるのは意味的におかしいので、2018/01/01 ~ 2018/03/31 とするべきだと感じます。

ただ、同じ、本当は業務的には年月なんだけど技術的な都合でDATE型にしている値でも、期間の FROM なのか TO なのかによって DB への格納方法が異なるのには違和感があります。

ただ、そもそも本当は業務的には「期間」というデータであってそれを技術的な都合でFROMとTOに分割しているのだと考えるとどっちてもいいんじゃないという気もする(どっちにしても業務的な意味とDBMSでの格納方法に齟齬がある)。


なお、2018/01/01 ~ 2018/03/31 のような形式で格納するようにすると、下記のような不安しか感じないコードを書いてしまうかもしれない。

select date_add(cast('2018/03/31' as date), interval 1 month)

なお、予想に反して?、期待したとおりの 2018/04/30 を返します。

なお、PHP の似たようなコードは予想通り?、期待に反して下記のような結果になります。

var_dump((new DateTime('2018/03/31'))->modify('+1 month')->format('Y/m/d'));
// string(10) "2018/05/01"
var_dump((new DateTime('2018/03/31'))->add(new DateInterval('P1M'))->format('Y/m/d'));
// string(10) "2018/05/01"

と思ってたらこんなのがあった。

SELECT PERIOD_ADD(200812, 1);
/* 200901 */

SELECT PERIOD_DIFF(200903, 200811);
/* 4 */

わざわざこんな関数が用意されているぐらいなので、MySQL で年月を表すデータ型は整数で良い?・・のかもしれない。