Questo è un problema classico e in realtà è più facile se si inverte la logica.
Lasciate che vi faccia un esempio.
Pubblicherò qui un periodo di tempo e tutte le diverse varianti di altri periodi che si sovrappongono in qualche modo.
|-------------------| 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
d'altra parte, lasciami pubblicare tutti quelli che non si sovrappongono:
|-------------------| compare to this one
|---| ends before
|---| starts after
Quindi, se riduci semplicemente il confronto a:
starts after end
ends before start
poi troverai tutti quelli che non si sovrappongono, e poi troverai tutti i periodi non corrispondenti.
Per il tuo esempio finale NOT IN LIST, puoi vedere che corrisponde a queste due regole.
Dovrai decidere se i seguenti periodi sono IN o FUORI dai tuoi intervalli:
|-------------|
|-------| equal end with start of comparison period
|-----| equal start with end of comparison period
Se la tua tabella ha colonne chiamate range_end e range_start, ecco un semplice SQL per recuperare tutte le righe corrispondenti:
SELECT *
FROM periods
WHERE NOT (range_start > @check_period_end
OR range_end < @check_period_start)
Nota il NON lì dentro. Poiché le due semplici regole trova tutte le righe non corrispondenti , un semplice NOT lo invertirà per dire: se non è una delle righe non corrispondenti, deve essere una di quelle corrispondenti .
Applicando qui una semplice logica di inversione per sbarazzarsi del NOT e si finisce con:
SELECT *
FROM periods
WHERE range_start <= @check_period_end
AND range_end >= @check_period_start