一か月を取得するクエリ

一か月のデータを取得する際に使用するクエリを紹介します。
mysql、postgress、SQL serverで同様の書き方がきることを確認していますので、
大体のデータベースで使えると思います。

ひと月分のデータが出力されないときの参考にしてみてください。

一か月を取得する書き方2つ

一か月を範囲指定する書き方はと不等号を利用した方法とbetweenを利用した方法の二種類があります。
コツは最初は「含む」、最後は「含まない」にすることです。

不等号で一か月

まずは不等号を利用した場合です。
日付列sample_dateに対して2月のデータを取得するwhere句です。


ひと月の最後に注目してください。日付は翌月一日にして「含まない」にしていますね。
「sample_date < ‘2020/03/01’」です。

sample_dateが年月日だけを持っているのであれば等号を利用するパターン
「sample_date <= ‘2020/02/29’」
でも問題ないでしょう。

ただ、ここを等号「<=」を含めた場合ではデメリットがあります。

月末の日付が一定でないことと(30日,31日の把握。うるう年2月の28日,29日)、
そして、秒、ミリ秒など細かくデータを持っている場合は考慮しなければなりません。

「sample_date <= ‘2020/02/29 23:59:59 …’」

しかし、不等号であれば「月末の日付」や「秒」を把握する煩わしさはなくなるためオススメです。

ちなみに、日付開始の0時0分0.00…秒からカウントしたいので等号を含めます。
「 ‘2020/02/01’ <= sample_date 」

betweenで一か月

次にbetweenの書き方です。


解説していきます。

betweenは最初も、最後も「含む」になります。

where sample_date between ‘2020/02/01’ and ‘2020/03/01’
と書いたとき
where ‘2020/02/01’ <= sample_date and sample_date <= ‘2020/03/01’
と同義なので注意が必要です。

betweenの仕様として最後を「含む」になってしまっているので、「月末の日付」や「秒」を把握する煩わしさがある状態です。

そこで、where句に条件

「and sample_date != ‘2020/03/01’」

を一つ足して対応します。

where ‘2020/02/01’ <= sample_date
and sample_date <= ‘2020/03/01’
and sample_date != ‘2020/03/01’

つまり実質

where ‘2020/02/01’ <= sample_date
and sample_date < ‘2020/03/01’

これで最後の日付を「含まなく」なりましたので、

betweenを使用した場合でも「月末の日付」や「秒」を把握する煩わしさはなくなりました。

どちらを選ぶかは文化とパフォーマンスで決める

どちらの書き方を採用するかは、好みやチームの文化で選んでみてください。

チーム内で不等号しか使用しない文化の中でbetweenを持ち込んでしまうと、
チームの方が読みづらいと感じてしまいます。逆も然りです。

また、パフォーマンスがどうしても必要な場合はインデックス+betweenを検討しましょう。
以前よりbetweenではインデックスを利用できるぶん、不等号よりパフォーマンスがでるといわれているためです。

ただ、最近のSQLは頭が良くなっている可能性があります。
不等号でもインデックスを利用するように解釈しているかもしれません。
その場合はパフォーマンスに差異がない可能性がありますので、あしからず。

おわりに

一か月で範囲指定は、集計に表示と、ビジネスではよく使う表現になりますので、
どなたかの参考になれば嬉しいです。

ではまた。