Problème de SQL.

Résolu
Noubli -  
 Noubli -
Bonjour,
Je me casse la tête à essayer de trouver une requête en SQL un peu compliquée.
En fait, j'ai une table "Reservation", avec une heuredébutreservation et une heurefinreservation.
Ce que je voudrais faire, c'est à partir d'un horaire minimum, (exemple 5:00 AM) et une heure maximum (11:00 PM), avoir une liste des "créneaux" qui restent.

Par exemple, si j'ai une reservation entre 8:00 AM et 11:00 AM, je voudrais que la requete me retourne :
5:00 AM - 8:00 AM
11:00 AM - 11:00 PM.

Je sais pas si je suis bien clair et je suis même pas sûr que ca soit possible en SQL uniquement.

Avez vous une piste à me donner? (pas d'autres langages en renfort).

Merci d'avance,
A voir également:

8 réponses

othanga
 
bonjour,

peut-être la solution viendrait-elle d'un truc du genre
select debut, min(fin) from (
select a.heure_de_fin as debut, b.heure_de_debut as fin
from reservations a, reservations b
where a.heure_de_fin < b.heure_de_debut
union
select :horaire_minimum as debut, b.heure_de_debut as fin
from reserations
union
select heure_de_fin as debut, :horaire_maximum as fin
) resas
group by debut

les horaire_minimum et horaire_maximum seraient à remplacer par les 5:00 AM et 11:00 PM de ton exemple
0
d_laurent23 Messages postés 5 Date d'inscription   Statut Membre Dernière intervention  
 
Bonsoir,
Si tu traites tes résultats de manière itératives, tu dois pouvoir tester l'heure de fin de réservation du créneau à l'indice i et le comparer avec la valeur du début de la réservation qui l'a suit (si tu as un ORDER BY dans ta requête).

Tiens-nous au courant.
Cordialement,
Laurent.
0
Noubli
 
J'ai bien peur que le SQL de 'haut-niveau" me dépasse carément.
0
P@t@ch0n Messages postés 565 Date d'inscription   Statut Membre Dernière intervention   85
 
Hum, je suis pas bien certain d'avoir saisi, mais d'après ce que j'ai compris, je vois rien de sorcier là-dedans.

SELECT heureDebutReservation, heureFinReservation 
FROM reservation 
WHERE ( heureDebutReservation BETWEEN creneauHeureDebut AND creneauHeureFin )
OR ( heureFinReservation BETWEEN creneauHeureDebut AND creneauHeureFin);


Bien évidemment il faut que les formats soient identiques.
0
Noubli
 
Je vois pas bien ce que tu appelles creneauHeureDebut et creneauHeureFin dans ta requete :/
0
P@t@ch0n Messages postés 565 Date d'inscription   Statut Membre Dernière intervention   85
 
Par exemple, si j'ai une reservation entre 8:00 AM (creneauDebut) et 11:00 AM (creneauFin)
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
othanga
 
re

les créneaux début et fin dont parle p@t@chon sont en fait respectivement tes fin et début de réservation.
=> pour utiliser des zones nommées comme celles de p@t@chon, tu réalise une extraction de tes réservations (début créneau = fin réservation & fin créneau = début réservation suivante) que tu déverses dans une nouvelle table où tu vas pouvoir requêter sans souci.

si tu ne peux ou ne veux pas introduire une table supplémentaire, tu requêtes des débuts et des fins de créneaux en prenant respectivement des fins et des débuts de réservation. Comme la fin de la réservation ne sera jamais antérieure au début figurant dans ta requête, tu es obligé d'interroger le produit réservations x réservations.
À compter de ce moment, tu peux ne retenir que les lignes ou fin < début. Ce faisant, pour une fin, tu obtiens une multitude de débuts ultérieurs, il te suffit de prendre le plus petit.

ex:
dans la table RESA, tu as 4 réservations :
R1 : ( 7h ; 9h ) -- de 7h à 9h
R2 : ( 9h30 ; 11h )
R3 : ( 12h ; 16h30 )
R4 : ( 17h ; 22h )

si tu requêtes RESA x RESA en demandant fin < debut
(select a.fin, b.debut from RESA a, RESA b where a.fin < b.debut)
alors tu obtiens :
x1 : ( 9h ; 9h30 ) -- la fin de R1 avec le début de R2
x2 : ( 9h ; 12h ) -- la fin de R1 avec le début de R3
x3 : ( 9h ; 17h ) -- la fin de R1 avec le début de R4
x4 : ( 11h ; 12h ) -- la fin de R2 avec le début de R3
x5 : ( 11h ; 17h ) -- la fin de R2 avec le début de R4
x6 : ( 16h30 ; 17h ) -- la fin de R3 avec le début de R4

arrivés ici, il y a des trucs bien (x1 est bien un créneau) et d'autres qui vont pas du tout (x2 = créneau + résa)

c'est là qu'intervient le second select, celui où l'on ne conserve le min(fin) pour chaque début
(select fin, min(debut) from ce_que_je_viens_de_calculer group by fin)
le min(fin) pour 9h => min(fin) dans x1, x2 & x3 => 9h30
=> ( 9h ; 9h30 )
le min(fin) pour 11h => min(fin) dans x4 & x5 => 12h
=> ( 11h ; 12h )
le min(fin) pour 16h30... vu qu'il n'y a qu'une combinaison, le choix est vite fait
=> ( 16h30 ; 17h )

et voilà !
tu as tes créneaux, tes plages non réservées, le tout en une requête.

Elle est pas belle la vie ?
0
Noubli
 
Super, c'est exactement ce que je voulais :).
Merci beaucoup !!!!

Il reste juste un hic, il n'y a pas dans cette technique les notions d'heure de début de possibilité de reservation et de fin de possibilité de reservation. (jsais pas si c'est clair).
Par exemple :
Dans ton exemple, si les reservations commencent à 5:00 AM, je voudrais qu'il y ai aussi une ligne :
(5:00;7:00)
(et idem pour la fin).
Pour l'instant, j'ai reussi à m'en sortir en insérant une reservation qui commence et finit à 5:00 AM (de même pour la fin), mais ça m'a l'air un peu sale comme technique non? (bien sûr je l'efface à la fin de mon block de requête).

En tout cas, merci beaucoup pour tes explications, c'était très clair.

Noubli.
0
othanga
 
effectivement, dans la démonstration détaillée, il n'y a pas les "créneaux" extrèmes.
c'est pour ça que j'avais rajouté dans la 1ere requete présentée
...
UNION
SELECT :horaire_minimum as debut, b.heure_de_debut as fin
FROM reservations
UNION
SELECT a.heure_de_fin as debut, :horaire_maximum as fin
FROM reservations

notons au passage que c'est pas pratique car le 1er union renvoie autant de lignes qu'il y a de RESA
j'aurais du écrire :

UNION
SELECT :horaire_minimum as debut, MIN(b.heure_de_debut) as fin
FROM reservations
UNION
SELECT MAX(a.heure_de_fin) as debut, :horaire_maximum as fin
FROM reservations

explication avec la demo:
1. si tu remplaces horaire_minimum par 5h00, le 1er select te renvoie x0 : ( 5h00 ; 9h00 )
2. si tu remplaces horaire_maximum par 23h00, le 2nd select te renvoie x7 : (17h00 ; 23h00)
3. les UNION servent à rajouter les lignes x0 et x7 au résultat de ta requete initiale
4. le second select de la demo (celui qui renvoie debut, min(fin)) renverra en plus de tes créneaux ces 2 lignes rajoutées (note au passage que comme il n'existe qu'une seule ligne pour 5h et une seule pour 17h, le group by est instantané)

J'ai noté tes 5h et 23h sous forme de paramètre SQL, car aujourd'hui tu veux gérer de 5h à 23h.
Si demain tu veux gérer de 7h à 20h, tu n'auras qu'à changer les paramètres d'appel de ta requête.
Si par contre tu écris des constantes dans ta requête, il faudra que tu (ou ton remplaçant) aille retrouver la requête et la modifie avec les nouvelles valeurs

Ça te va ?
0
Noubli
 
Ah oui, effectivement, j'avais pas vu que c'était toi qui avait posté là-haut.
Et je pense que cette dernière partie j'aurais pu la faire tout seul en y réfléchissant bien.

Mais c'est là que je me rends compte que je suis assez nul en SQL.
Ca serait indiscret de te demander combien d'années d'expérience tu as dans ce domaine?

En tout cas merci beaucoup, c'est tout à fait ce dont j'avais besoin et j'ai pu bien comprendre avec tes explications, je mets le sujet en résolu.

Merci encore,

Noubli.
0