Schnittmenge von 2 Zeiträumen in MySQL (Logisches Problem, vllt auch ohne SQL-Kenntnisse mal reingucken ;))

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • Schnittmenge von 2 Zeiträumen in MySQL (Logisches Problem, vllt auch ohne SQL-Kenntnisse mal reingucken ;))

      Hi,

      ich hab n Problem bei ner Datenbanken-Aufgabe:

      Ich habe eine "Hotelverwaltung" wo Zimmer ab einem Datum bis zu einem Datum gebucht werden, wenn jetzt eine neue Buchung reinkommt, muss logischerweise überprüft werden, ob der neue Buchungszeitraum (auch mit von-bis-Datum) mit dem/den schon bestehenden eine Schnittmenge bildet.

      Das ganze ist wahrscheinlich weniger aufgrund der MySQL-Syntax ein Problem, sondern einfach weil ich mit der logischen Grundlage grade nicht klarkomm ^^

      BSP:

      Zimmer gebucht vom 01.01.2011 bis 09.01.2011
      Möglichkeiten:
      1. Neue Buchung 31.12.2010 bis 10.01.2011 (-> Neuer Zeitraum enthält den alten, Buchung nicht möglich)
      2. Neue Buchung 03.01.2011 bis 08.01.2011 (-> Alter Zeitraum enthält den neuen, Buchung nicht möglich)
      3. Neue Buchung 07.01.2011 bis 14.01.2011 (-> Zeiträume überschneiden sich am Ende, Buchung nicht möglich)
      4. Neue Buchung 29.12.2010 bis 03.01.2011 (-> Zeiträume überschneiden sich am Anfang, Buchung nicht möglich)

      Jemand ne Idee welche Abfragen nötig wären?
    • Hallo

      Könntest du nicht ein anderes Datumsformat für die interne Bearbeitung wählen, so dass Tage ab einen Tag X einfach fortlaufend gezählt werden? Dann könntest du durch einfache abfragen, ob der Anfang der neuen Buchung kleiner ist als das Ende der alten. Das Filtert 1-3. Punkt kannst du durch eine ähnliche Abfrage rausfiltern, indem du denn wenn-es-kleiner-ist-Zweig nochmal unterteilst und guckst ob auch das neues Ende kleiner ist als der alte Anfang, ansonsten halt immer Fehler. Problem ist nur, dass du noch Funktionen implementieren musst, die die zeiten umrechnen, sollte aber auch gehen.

      Tray

      Quellcode

      1. main()
      2. {
      3. for(;;)
      4. printf("DotaInside - ich war dabei!\n");
      5. }
    • Gingen nicht einfache If abfragen mit Laufvariablen? Wobei er noch unterscheidet, ob Ankunftszahl kleinergleich Abfahrtszeit (das fragt er ab, wenn die Tageszeiten vom 27. zum 02. werden, denn dann ist klar, dass der Monat auch wechselt) && Monatsankuftzahl kleiner Monatsabfahrtzahl (hier nochmal die Vergewisserung, dass der Monat dann wechselt, Kann sein, dass sie am gleichem Tag wieder abfahren <.<) Wenn dies nicht der Fall ist, dann ändert sich der Monat nicht, gg. Müsstest vielleicht noch eine Jahresbafrage machen wegen Buchungszeit vom 01.01.2010 bis zum 01.01.2011. Man kann da sehr pingelig sein, wenn man alle Fälle abfragt.
    • Ich hab auch gedacht, der Anfang der neuen Buchung muss größer sein, als das Ende der alten, aber eigentlich muss das doch garnicht sein, weil Daten die von dem ausgebuchten Termin ja auch möglich sind. Und dann wäre der Anfang der neuen Buchung halt kleiner (bzw. vor) dem Ende der alten Buchung. ?(

      Daws Layout der Tabellen könnte ich allerdings nach belieben verändern, wüsste aber nichts Geeigneteres.

      @matthe: Laufvariablen = Schleife nehm ich mal an. Das würde wahrscheinlich gehen, aber ist in MySQL etwas umständlich imo... Hab ich auch nochnie gemacht, aber theoretisch kann man in MySQL ja Funktionen schreiben und LOOP als Schleife gibt es auch.

      Irgendwelche logischen >/</= Abfragen wären mir lieber (falls überhaupt möglich)

      EDIT: Also ich probier mal deinen Ansatz zusammenzufassen (@ Tray):

      1. Ich geb nur ein Anfangsdatum und ne Dauer an. Bsp. ab dem 01.01.2011 7Tage lang.
      2. Ich gucke ob das neue Buchungsdatum größer als 01.01.2011 + 7 Tage ist, wenn ja kein Problem
      3. Falls das neue Datum kleiner ist als der 01.01.2011, gucke ich ob das neue Datum + die neue Dauer auch kleiner ist, als das alte Anfangsdatum.

      (Ich muss das nochma so aufschreiben, damit ich überhaupt selbst durchblick und du kannst ja vllt nochmal sagen, ob dus so gemeint hast ;))

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von ^woOt ()

    • benutz den befehl:
      NOT IN

      zb:

      select*
      from namederzimmertabelle
      where zimmer not in(
      select zimmer
      from zimmertabelle
      where Tag>31.12.2010
      and Tag<10.1.2011);

      edit:
      sry, von tag war mist
      hab jz meine alten infosys übengen rausgesucht gehabt und da war das beispiel mit vorlesungen,
      welche die einträge von_stunde und bis_stunde hatten

      ich hab mir das da ca. so aufgezeichnet:

      die roten balken sind die fälle für buchungen, die nicht eintreffen sollten

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Wotsengnagga ()

    • ^woOt schrieb:


      EDIT: Also ich probier mal deinen Ansatz zusammenzufassen (@ Tray):

      1. Ich geb nur ein Anfangsdatum und ne Dauer an. Bsp. ab dem 01.01.2011 7Tage lang.
      2. Ich gucke ob das neue Buchungsdatum größer als 01.01.2011 + 7 Tage ist, wenn ja kein Problem
      3. Falls das neue Datum kleiner ist als der 01.01.2011, gucke ich ob das neue Datum + die neue Dauer auch kleiner ist, als das alte Anfangsdatum.


      Ich meinte, dass man alle Buchungseinträge in drei Variablen speichert.
      Nummer; Anfang; Ende

      Wobei Anfang und Ende jeweils Integer sind (Ich kann nur C, könnte man auch mit Date-Structs machen, falls SQL das untersützt), die Nummer ist halt fortlaufen (ggf. auch überhaupt nicht nötig, kann wie gesagt kein SQL). Dann gibt der Benutzer also ein, dass eine Buchung vom 1.1.2011 bis zum 3.1.2011 geht. Das System rechner das ganze in vergangene Tage um, wobei der Startpunkt meinetwegen der 31.12.2010 ist. Dann Steht da also: Buchungsnummer 1; Anfang 1; Ende=3. Eine neue Buchung müsste also genauso eingetragen werden und alle Buchungen müssten auf Überdeckungen hinüberprüft werden. Also so etwas der Art:
      Schleife(Von 1 - Buchungsanzahl)
      Wenn Anfang(neuBuchung) < Ende(aktBuchung)
      Wenn Anfang(aktBuchung < Ende(neuBuchung)
      Mach weiter mit der Schleife
      Sonst
      Wenn Anfang(neuBuchung) > Ende(aktBuchung)
      Mach weiter mit der Schleife
      Sonst
      Gib Achtung Überschneidung zurück

      Ist wie gesagt wahrscheinlich etwas sehr in C gedacht und du sagtest bereits, dass Schleifen blöd zu implementieren wären, aber es ging um das Datumsformatprinzip, was eben die Abfragen ob ein Zeitraum den anderen überdeckt sehr einfach gestalltet.

      Tray

      Quellcode

      1. main()
      2. {
      3. for(;;)
      4. printf("DotaInside - ich war dabei!\n");
      5. }
    • nun, wenn man das Ganze reduziert, gibt es vier Fälle, die unabhängig voneinander eintreten können, von welchen aber zumindest einer gegeben sein muss, dass das Zimmer besetzt ist.
      Diese Fälle sind immer dann, wenn ein Eckpunkt eines Zeitraumes zwischen den zwei Punkten eines anderen zeitraumes liegt.

      arbeiten wir einfach mal mit Buchstaben.

      Buchung a und b, 1 ist anfang, 2 ist ende.

      somit haben wir die 4 Eckpunkte a1, a2, b1 und b2.

      das Zimmer ist belegt, wenn a1<b1<a2 ODER a1<b2<a2 ODER b1<a1<b2 ODER b1<a2<b2
      jetzt nimmst du diese bedingung, um eine Menge zu Bilden, schnappst dir alle Zimmer und feuerst die NOT IN Funktion auf diese Menge ab, übrig bleiben die Zimmer, die tatsächlich frei sind.

      ich hab oben btw Bullshit geschrieben, sie können nicht gänzlich unabhängig voneinander eintreten, wenn es zu Überschneidungen kommt, treten immer genau zwei davon auf.

      Somit würde es, wie mir gerade eingefallen ist, reichen, drei beliebige aus den vier Bedingungen zu wählen.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von naphack ()

      ༼ つ ◕_◕ ༽つ GIVE DIRETIDE
    • SQL-Abfrage

      1. SELECT COUNT(*) AS count
      2. FROM myTable
      3. WHERE ($start BETWEEN timeIn AND timeOut) OR
      4. ($end BETWEEN timeIn AND timeOut) OR
      5. ($start < timeIn AND $end > timeOut)

      $start = Timestamp des Tages, von welchem ab man das Zimmer buchen möchte.
      $end = Timestamp des Tages, an welchem man das Zimmer verlässt.

      timeIn = Name der Spalte in myTable für den Beginn einer Buchung
      timeOut = Name der Spalte in myTable für das Ende der Buchung

      myTable = Name der Tabelle mit den Buchungen

      Wenn count > 0 als Ergebnis zurück kommt, überschneidet sich der Zeitraum $start bis $end mit einem bereits in der Tabelle gebuchten Zeitraum.

      1. Bedingung: $start darf nicht in einem gebuchten Zeitraum liegen
      2. Bedingung: $end darf nicht in einem gebuchten Zeitraum liegen
      3. Bedingung: Trifft zu, wenn $start und $end einen bereits gebuchten Zeitraum umschließen