Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Comparando períodos


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