Mysql
 sql >> Base de données >  >> RDS >> Mysql

Comparer des plages de dates

C'est un problème classique, et c'est en fait plus facile si vous inversez la logique.

Laissez-moi vous donner un exemple.

Je posterai une période de temps ici, et toutes les différentes variations d'autres périodes qui se chevauchent d'une certaine manière.

           |-------------------|          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

par contre, laissez-moi poster tous ceux qui ne se chevauchent pas :

           |-------------------|          compare to this one
     |---|                                ends before
                                 |---|    starts after

Donc, si vous réduisez simplement la comparaison à :

starts after end
ends before start

puis vous trouverez tous ceux qui ne se chevauchent pas, puis vous trouverez toutes les périodes qui ne correspondent pas.

Pour votre dernier exemple NOT IN LIST, vous pouvez voir qu'il correspond à ces deux règles.

Vous devrez décider si les périodes suivantes sont DANS ou EN DEHORS de vos plages :

           |-------------|
   |-------|                       equal end with start of comparison period
                         |-----|   equal start with end of comparison period

Si votre table comporte des colonnes appelées range_end et range_start, voici quelques instructions SQL simples pour récupérer toutes les lignes correspondantes :

SELECT *
FROM periods
WHERE NOT (range_start > @check_period_end
           OR range_end < @check_period_start)

Notez le PAS là-dedans. Étant donné que les deux règles simples trouvent tous les éléments non correspondants lignes, un simple NOT l'inversera pour dire :si ce n'est pas l'une des lignes non correspondantes, ce doit être l'une des lignes correspondantes .

Appliquez une simple logique d'inversion ici pour vous débarrasser du NOT et vous vous retrouverez avec :

SELECT *
FROM periods
WHERE range_start <= @check_period_end
      AND range_end >= @check_period_start