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が入れ替わる可能性がある場合は、他の条件をつけましょう。