Este é um problema clássico e, na verdade, é mais fácil se você inverter a lógica.
Deixe-me lhe dar um exemplo.
Vou postar um período de tempo aqui e todas as diferentes variações de outros períodos que se sobrepõem de alguma forma.
|-------------------| 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
por outro lado, deixe-me postar todos aqueles que não se sobrepõem:
|-------------------| compare to this one
|---| ends before
|---| starts after
Portanto, se você simplesmente reduzir a comparação para:
starts after end
ends before start
então você encontrará todos aqueles que não se sobrepõem e, em seguida, encontrará todos os períodos não correspondentes.
Para seu exemplo final NOT IN LIST, você pode ver que ele corresponde a essas duas regras.
Você precisará decidir se os seguintes períodos estão DENTRO ou FORA de seus intervalos:
|-------------|
|-------| equal end with start of comparison period
|-----| equal start with end of comparison period
Se sua tabela tem colunas chamadas range_end e range_start, aqui está um SQL simples para recuperar todas as linhas correspondentes:
SELECT *
FROM periods
WHERE NOT (range_start > @check_period_end
OR range_end < @check_period_start)
Observe o NÃO aí. Visto que as duas regras simples encontram todas as linhas não correspondentes , um simples NÃO irá inverter para dizer: se não é uma das linhas não correspondentes, tem que ser uma das correspondentes .
Aplicando a lógica de reversão simples aqui para se livrar do NÃO e você acabará com:
SELECT *
FROM periods
WHERE range_start <= @check_period_end
AND range_end >= @check_period_start