MySQLでは、日付範囲のリスト(範囲開始と範囲終了)があるとします。例:
10/06/1983 to 14/06/1983
15/07/1983 to 16/07/1983
18/07/1983 to 18/07/1983
また、別の日付範囲に、リストにすでに含まれている範囲が含まれているかどうかを確認したいのですが、どうすればよいでしょうか?
例えば
06/06/1983 to 18/06/1983 = IN LIST
10/06/1983 to 11/06/1983 = IN LIST
14/07/1983 to 14/07/1983 = NOT IN LIST
ベストアンサー1
これは古典的な問題であり、論理を逆にすると実際には簡単になります。
例を挙げてみましょう。
ここでは、1 つの期間と、何らかの形で重複する他の期間のさまざまなバリエーションをすべて投稿します。
|-------------------| compare to this one
|---------| contained within
|----------| contained within, equal start
|-----------| contained within, equal end
|-------------------| contained within, equal start+end
|------------| not fully contained, overlaps start
|---------------| not fully contained, overlaps end
|-------------------------| overlaps start, bigger
|-----------------------| overlaps end, bigger
|------------------------------| overlaps entire period
一方、重複しないものはすべて投稿します。
|-------------------| compare to this one
|---| ends before
|---| starts after
したがって、比較を次のように単純に縮小すると、
starts after end
ends before start
すると、重複しないものがすべて見つかり、一致しない期間もすべて見つかります。
最後の NOT IN LIST の例では、これら 2 つのルールに一致することがわかります。
次の期間が範囲内か範囲外かを判断する必要があります。
|-------------|
|-------| equal end with start of comparison period
|-----| equal start with end of comparison period
テーブルに range_end と range_start という列がある場合、一致する行をすべて取得する簡単な SQL を次に示します。
SELECT *
FROM periods
WHERE NOT (range_start > @check_period_end
OR range_end < @check_period_start)
注意してくださいない2つの簡単なルールで、一致しない行の場合、単純な NOT で反転して次のように表示されます。一致しない行の1つでない場合は、一致する行の1つである必要があります。
ここで単純な逆ロジックを適用して NOT を取り除くと、次のようになります。
SELECT *
FROM periods
WHERE range_start <= @check_period_end
AND range_end >= @check_period_start