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
Então, 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 então você encontrará todos os períodos não correspondentes.
Para o 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 tiver 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 lá. Como as duas regras simples encontram todos os não correspondentes linhas, um simples NOT irá invertê-lo para dizer:se não for uma das linhas não correspondentes, deve ser uma das correspondentes .
Aplicando uma lógica de reversão simples aqui para se livrar do NOT e você terminará com:
SELECT *
FROM periods
WHERE range_start <= @check_period_end
AND range_end >= @check_period_start