Freie Zimmer aus Belegungstabelle auslesen?!?

  • Hallo!

    Ich habe folgendes Problem. Es besteht eine Belegungstabelle wo alle Aufenthalte/Buchungen gespeichert werden. Sie beinhaltet neben sonstigem Zeugs die Zimmernummer, ein Ankunfts- und ein Abreisedatum.

    Ich möchte nun nach Eingabe des Ankunfts- und Abreisedatums alle Zimmer ausgeben, die in dieser Zeitspanne nicht belegt sind.

    Klingt doch irgendwie einfach, oder? Ich komm aber beim besten Willen ned drauf, wie das funktionieren könnte. Damit man mal alle Zimmer kennt habe ich eine eigene Tabelle angelegt, wo nur die Zimmernummern drinnen stehen.

    Es handelt sich übrigens um eine MySQL-Datenbank.

    Vielen Dank für eure Hilfe!!

    Schönen Abend,
    chrisi

  • naja ein zimmer ist genau (heute, oder einem bestimmten datumsbereich)dann nicht belegt, wenn
    a) das ankunftsdatum nicht in der vergangenheit (relativ zum definierten zeitraum)liegt UND gleichzeitig
    b) das abreisedatum nicht in der zukunft(wieder rel.v.def.zeitraum) liegt.

    und das ganze musst halt mit der reinen zimmernummer-tabelle joinen, und dir genau die rauspicken wo auf der "reservierung"-seite vom join nix steht.

    rest musst schon selber machen (weil: wenns für uni/schule ist, damits auch wirklich dein geistiges produkt ist; wenns kommerziell ist: weil du dafür gezahlt wirst, dass dus machst.)

  • Hi!

    Danke für eure Hilfe. Mein Ergebnis ist jetzt bisher so:

    SELECT *
    FROM zimmerNr
    LEFT OUTER JOIN belegung ON belegung.znr = zimmerNr.znr
    WHERE (
    (
    (
    '2006-09-27'
    BETWEEN belegung.von
    AND belegung.bis -1
    )
    AND (
    '2006-09-29'
    BETWEEN belegung.von +1
    AND belegung.bis
    )
    ) IS NULL
    )

    Funktionieren tuts nicht aber es müsste mal ein Ansatz sein.

    Mr.Radar: Weder noch.. ich mach das für unsere Frühstückspension. Aber du hast schon recht, selber denken schadet auch nicht... ;)


    chrisi

  • Beim Outer Join bleibt eine Tabelle immer ganz enthalten (manche Tupel eventuell auch mehrfach), daher wird in deinem Fall jede Zimmernummer zumindest ein Mal angezeigt, ganz egal wie die Belegungen aussehen.

    Probier es mal so:

    Den Teil mit Between habe ich jetzt von dir übernommen und nicht durchgeschaut, aber falls der das tut das ich annehme (alle Zimmernummern rausfiltern, die belegt sind) sollte es vom Prinzip her funktionieren (mal abgesehen von eventuellen Syntaxfehlern meinerseits).

    Noch eine Anmerkung: Ich würde die Tabelle mit allen Nummern nicht zimmerNr nennen (das ist nur ein Attribut) sondern einfach nur Zimmer, weil die Tabelle logisch gesehen alle Zimmer speichert (auch wenn du abgesehen von der Nummer keine Attribute drinnen hast: vielleicht willst du ja mal erweitern).

  • Den Teil mit Between habe ich jetzt von dir übernommen und nicht durchgeschaut, aber falls der das tut das ich annehme (alle Zimmernummern rausfiltern, die belegt sind) sollte es vom Prinzip her funktionieren (mal abgesehen von eventuellen Syntaxfehlern meinerseits).

    Noch eine Anmerkung: Ich würde die Tabelle mit allen Nummern nicht zimmerNr nennen (das ist nur ein Attribut) sondern einfach nur Zimmer, weil die Tabelle logisch gesehen alle Zimmer speichert (auch wenn du abgesehen von der Nummer keine Attribute drinnen hast: vielleicht willst du ja mal erweitern).

    Ich hab jetzt mal beides probiert - MINUS und EXCEPT. Beides funktioniert aber nicht. Keine Ahnung was es da noch gibt.

    Der Vorschlag von Mr. Radar mit den Joins wäre mir sonst auch sympathisch vorgekommen. So auf die Art: gib mir alle Belegungen in dem Zeitraum aus der Belegungstabelle und vergleiche die Znr mit den Znr aus der Zimmer-Tabelle und gib die aus, die nicht vorkommen. Aber wie man das realisiert....

    lg, chrisi

    PS: Die Tabelle heißt jetzt Zimmer.

  • Probier's mal damit:

    SELECT znr FROM Zimmer WHERE znr NOT IN(
    SELECT znr FROM Zimmer JOIN belegung ON( Zimmer.znr = Belegung.znr)
    WHERE Belegung.von BETWEEN '2006-10-04' AND '2006-10-06'
    OR Belegung.bis BETWEEN '2006-10-04' AND '2006-10-06'
    )

    mfg

  • Probier's mal damit:

    SELECT znr FROM Zimmer WHERE znr NOT IN(
    SELECT znr FROM Zimmer JOIN belegung ON( Zimmer.znr = Belegung.znr)
    WHERE Belegung.von BETWEEN '2006-10-04' AND '2006-10-06'
    OR Belegung.bis BETWEEN '2006-10-04' AND '2006-10-06'
    )

    mfg

    Hi! Danke auch für deinen Vorschlag.. so auf Anhieb funktionierts nicht. Liegt glaub daran, dass mySQL keine Subselects kann.. zumindest nach http://www.perlunity.de/perl/forum/thread_014806.shtml .

    Aber sonst schmeiß ich die zimmer-table wieder weg und mach das dann softwaremäßig.. Also wenn Zimmer 1 und Zimmer 2 belegt sind, sind die anderen frei.

    lg, chrisi

  • @Burgi's Vorschlag: NOT IN ist sicher ohnehin die professionellere Variante, obwohl ich eher Anhänger von EXCEPT/MINUS bin.

    Von der Auswahl der freien Zimmer her (d.h. das Konstrukt mit NOT IN) dürfte es funktionieren, aber die Where-Bedingung im 2. Select ist fehlerhaft. Es reicht nicht zu prüfen ob von oder bis zwischen dem gewünschten Reservierungszeitraum ist, denn es könnte - in diesem Beispiel - jemand bereits vor dem 4.10. anreisen und nach dem 6.10. abreisen, wodurch das Zimmer dann fälschlicherweise als frei ausgegeben würde. Stattdessen muss man explizit prüfen ob "von" vor dem 6.10. UND "bis" nach dem 4.10. ist.

    Den Join zwischen Zimmer und belegung kann man sich in diesem Fall sparen, da man keine Attribute von Zimmer braucht, die es nicht auch in belegung gibt (bzw. in diesem Fall hat Zimmer nicht einmal zusätzliche Attribute).

  • So.. langsam hänge ich schon ganz schöne lange an dem Problem. Was jetzt mal fix funktioniert ist die Abfrage der belegten Zimmer. Jetzt gehts nur noch um das mengenmäßige Abziehen der Resultate. Also wenn Zimmer 2 und 4 belegt, sind die anderen frei. Leider krieg ich das aber absolut nicht hin.
    Kann denn mySQL keine subselects? Bzw. wie finde ich die Version heraus? (Die DB wird nicht von mir gehostet.) phpinfo.php sagt: Client API version 5.0.24.

    Tut mir leid wenn ich schön langsam mit dem Thema nerve...

    lg, chrisi

  • Ich weiß dass eine frühere Version von mySQL mal keine Subselects kannte, aber ich weiß nicht mehr genau bis zu welcher Version das so war. Soweit ich weiß werden sie von aktuellen Versionen aber unterstützt (ohne Gewähr). Probier es mal mit einfacheren Beispielen, nur um herauszufinden ob es wirklich am Subselect liegt. Probier auch mal EXCEPT/MINUS mit einem einfacheren Beispiel aus. Wenn die beiden Konstrukte wirklich nicht unterstützt werden muss man sich wohl was anderes einfallen lassen.

    Edit: Notfalls würde ich die 2 Statements separat absetzen und das MINUS in der Applikation nachbauen (auch wenn's hässlich ist: was anderes fällt mir momentan nicht ein).

  • Select version() sagt mir gerade, dass ich Version 4.0.23-Max-log verwende. Also schon ziemlich alt würd ich meinen. (Fragt sich dann nur, was die Client API version 5.0.24. ist. Wird wohl mit dem PHP zusammenhängen?!?)

    Das EXCEPT/MINUS wird dann ja auch nicht gehen, weil da ja auch ein Subselect vorkommt.

    Ich werds wohl wirklich im Programm machen. In absehbarer Zeit ändert sich die Anzahl der Zimmer nicht. Und wenn, dann ists auch nicht DIE wahnsinns Umstellung.

    Vielen Dank dann für eure Mühe!

    lg, chrisi

    EDIT: Ich hab grad mit meinem Provider gesprochen. Ich kann auch mySQL 5.0 oder 5.1 haben. Dort wirds dann funktionieren! :) *freu*

  • JUHUU, ich hab jetzt mySQL 5.0 und jetzt funktionierts. Für alle Interessierten, die vielleicht mal dasselbe Problem haben:

    Code
    select a.znr from zimmer as a WHERE a.znr NOT IN
    (
    Select b.znr from belegung as b WHERE
    ((date_add('2006-09-15',interval 1 hour) BETWEEN b.von AND b.bis)
    or
    (date_add('2006-09-27',interval -1 hour) BETWEEN b.von AND b.bis)
    or
    (b.von BETWEEN date_add('2006-09-15',interval 1 hour) AND date_add('2006-09-27',interval -1 hour)))
    )

    Vielen Dank für eure Hilfe! Hätte ich gleich die richtige Version gehabt, hätten eure Vorschläge wahrscheinlich auf Anhieb funktioniert!

    lg,
    chrisi

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!