Contrôler si une période est couverte par un ou plusieurs Intervals de dates

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

15 sept. 2015, 09:42

Bonjour à tous,

Je viens vous soumettre un problème auquel je suis confronté pour tenter d'avoir d'autres approches que la mienne :)

Le besoin : je dispose de plusieurs plages de dates (qui ne sont pas nécessairement consécutives) et je souhaite contrôler si l'intervalle demandé par l'utilisateur comporte des "trous".

Par exemple, je dispose de 3 réservations :
- du "01/09/2015" au "10/09/2015"
- du "11/09/2015" au "15/09/2015"
- du "20/09/2015" au "25/09/2015"

Si l'utilisateur indique un intervalle du 2 au 8 ou du 7 au 12, il n'y a pas d'options / de trous, la période demandée est intégralement couverte par une ou par deux réservations.
SI l'utilisateur indique un intervalle du 12 au 18, la période demandée n'est pas intégralement couverte, que ce soit par une ou plusieurs réservations.

Voyez-vous une solution en SQL pour contrôler ce genre de chose ? (et histoire de corser le tout, je dois assurer la compatibilité avec différents SGBD, du coup s'il existe une fonction miracle propre à MySQL, je ne pourrais hélas pas l'exploiter, mais ça sera toujours bon de savoir que je suis pas le seul à m'arracher les cheveux sur ce problème ;))

Au pire je passerais par du code, mais j'ai peur que ce soit assez lourd comme traitement (je n'ai pas encore vraiment réfléchit au meilleur moyen d'effectuer ce type de contrôle et recherche en priorité une solution sql)

Merci d'avance de vos suggestions et bonnes idées :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

Avatar du membre
Administrateur PHPfrance
Administrateur PHPfrance | 9782 Messages

15 sept. 2015, 14:30

Une idée qui me vient comme ça, (en algo, à voir si il faut le faire en PHP ou si c'est faisable directement en SQL) :

Je prendrai la date la plus ancienne et la date la plus récente parmi mes intervalles, et je calculerai le nombre de jours entre ces deux dates. (ça me donne le nb de jours consécutifs)
Ensuite je comparerai ce résultat au cumul du nombre de jour de chaque période.

Si les résultats sont identiques => les jours sont consécutifs.

En SQL, tu dois pouvoir faire appel à la fonction DATEDIFF(DAY, date_debut, date_fin)
Quand tout le reste a échoué, lisez le mode d'emploi...

Avatar du membre
Modérateur PHPfrance
Modérateur PHPfrance | 10684 Messages

15 sept. 2015, 18:24

Hello et merci :)

J'y avais bien pensé effectivement, mais je ne vois pas de solution en SQL avec ce système. Le problème est que si la période est par exemple du 14 au 21, cela donne une valeur de 7 jours. Si je fais la somme des jours des périodes concernée (11-15 et 21-25), j'obtiens 11 jours couvert alors que j'ai un trou de 5 jours...

Il faudrait que je puisse faire un max() - au sens php pour comparer deux valeurs - entre les dates de début des plages et la date de début de l'intervalle pour que le calcul se fasse du 14 au 15 et non du 11 au 15... je vais voir si je m'en tire avec du case/when :)
Ce n'est pas en améliorant la bougie que l'on a inventé l'ampoule...

ViPHP
ViPHP | 928 Messages

22 sept. 2015, 17:14

Plutôt que d'avoir 3 entrées dans ta table :
- du "01/09/2015" au "10/09/2015"
- du "11/09/2015" au "15/09/2015"
- du "20/09/2015" au "25/09/2015"

Tu devrais lors de l'insertion faire en sorte qu'il n'y en ait que deux :
- du "01/09/2015" au "15/09/2015"
- du "20/09/2015" au "25/09/2015"

Ainsi il est très facile ensuite de pouvoir faire :
SELECT *
FROM reservations
WHERE dateStart <= :dateStartDeLutilisateur
   AND dateEnd >= :dateEndDeLutilisateur
Il faudrait ensuite probablement une seconde requête pour récupérer les réservations exactes, dans une table avec cette fois les 3 entrées. Tout dépend de l'organisation des données.