2016-12-20

tobijibu

MySQLである期間の情報を特定の期間に該当するかで抽出する

12/1~12/31の期間に稼働中のユーザーを取得するとしましょう。ユーザーの稼働データは下記とします。

date
+------+------------+------------+
| name | start      | end        |
+------+------------+------------+
| A    | 2016-11-30 | 2016-12-30 |
| B    | 2016-12-04 | 2016-12-10 |
| C    | 2016-12-25 | 2017-01-03 |
| D    | 2016-11-30 | 2017-01-03 |
| E    | 2016-11-20 | 2016-11-26 |
| F    | 2017-01-03 | 2017-01-07 |
+------+------------+------------+

このようなデータの場合に、Aさん、Bさん、Cさん、Dさんが該当で、Eさん、Fさんは除外にしたいです。

SQLで抽出するには下記のSQLで抽出します。

SELECT * FROM date
WHERE
  ('2016-12-01' BETWEEN start AND end)
  OR
  ('2016-12-31' BETWEEN start AND end)
  OR
  (start >= '2016-12-01' AND end <= '2016-12-30');

条件は以下の3つです。

  • 開始日がstart~endの間にあるか
  • 終了日がstart~endの間にあるか
  • 開始日と終了日が期間内にあるか

ポイントは1つめと2つめの条件です。BETWEENに列名を指定するのではなく、期間開始日と、終了日を指定します。こうすることで開始日と終了日がstart〜endの間のデータを絞ることができるので、12/1より以前に開始したユーザーや、12/31以降も稼働しているユーザーを抽出できます。そして、3つめの条件を見ることで、12/1以降に稼働開始して、12/31以前に稼働終了したユーザーも同時に抽出できます。

このパターンを利用する注意点は、必ずstartとendは入れ替わることが無いことが条件になります。つまり、全てのデータにおいて、date1カラムがdate2カラムの「後」にならないことが条件です。date1とdate2が入れ替わる可能性がある場合は、他の条件をつけましょう。