Elexender: MySQL Abfrage mit Datum

Hallo,

ich habe eine Tabelle für Reisebuchungen. Dort werden die Daten ca. folgendermaßen gespeichert:

Anreise | Abreise | Sonstige Daten
Anreise und Abreise sind vom Typ Date - 00-00-0000

Nun habe ich x Buchungen in der Tabelle und muss eine weitere hinzufügen. Dabei muss ich prüfen, ob bestimmter Zeitraum bereits belegt ist.

Beispiel:

Buchung, die bereits vorhanden ist:

Anreise: 10-01-2006
Abreise: 20-01-2006

Buchung, die gespeichert werden soll:

Anreise: 11-01-2006
Abreise: 15-01-2006

Wie kann ich nun mit einer SQL Anfrage feststellen, dass der Zeitraum von 11-01 bis 15-01 nicht verfügbar ist, weil es bereits eine Buchung von 10-01 bis 20-01 gibt?

Danke für die Hilfe.
Alexander.

  1. echo $begrüßung;

    Wie kann ich nun mit einer SQL Anfrage feststellen, dass der Zeitraum von 11-01 bis 15-01 nicht verfügbar ist, weil es bereits eine Buchung von 10-01 bis 20-01 gibt?

    Verwende eine Spalte vom Typ DATE.

    Wenn du einen String im Format TT-MM-JJJJ nimmst, bleibt dir nichts anderes übrig, als ihn jedes Mal in Einzelteile zu trennen und diese dann zu vergleichen. In der Schreibweise JJJJ-MM-TT ist er zwar einfacher vergleichbar, aber noch besser kann dich MySQL unterstützen, wenn du den Typ DATE nimmst. MySQL kann dann Kalenderbesonderheiten berücksichtigen. Außerdem gibt es eine ganze Menge Date and Time Functions. Schau dir dieses Kapitel mal an, dann bekommst du einen Überblick über diese Funktionen und findest dann bestimmt auch was passendes.

    echo "$verabschiedung $name";

    1. Hallo echo "$verabschiedung $name";

      Verwende eine Spalte vom Typ DATE.

      Hat er das nicht bereits getan (Wer lesen tut, ist im Vorteil?):

      Anreise und Abreise sind vom Typ Date - 00-00-0000

      Die Frage des OP richtet sich mehr auf das Problem, wie man mit einer
      Abfrage feststellt, dass sich zwei definierte Zeiträume überschneiden.
      Das ist recht einfach:

      • Das Anfangsdatum einer Probe (neuer Datensatz) darf nicht innerhalb
          des Zeitraums eines existierenden Vergleichsdatensatzes liegen
      • dito für das EndDatum der Probe

      In SQL wahrschweinlich etwa so ausgedrückt:

        
      SELECT 1 FROM MeineTabelle  
      WHERE @neuesAnreiseDatum NOT BETWEEN [Anreise] AND [Abreise]  
      AND   @neuesAbreiseDatum NOT BETWEEN [Anreise] AND [Abreise]  
      AND /* ... weitere vergleiche für z.b. dasselbe Mietobjekt */  
      
      

      @neues~ stehen für Variablen die an jener Stelle eingefügt werden sollen

      Wenn NULL zurückkommt schlagen beide Bedingungen fehl, was heisst,
      mindestens eines der neuen Daten liegt innerhalb eines Zeitraums, der
      bereits "reserviert" ist.

      @dedlfix: deswegen gab's auch den Minuspunkt, weil deine Antwort keine Hilfe auf das Problem beinhaltet. Hast du dir den Pluspunkt selbst gegeben?

      Ciao, Frank

      1. hi,

        Verwende eine Spalte vom Typ DATE.

        Hat er das nicht bereits getan (Wer lesen tut, ist im Vorteil?):

        Tja, wer weiß, ob er's wirklich getan hat?

        Anreise und Abreise sind vom Typ Date - 00-00-0000

        Das hinten stehende Muster passt jedenfalls nicht zu DATE, denn das Format dafür ist YYYY-MM-DD.

        gruß,
        wahsaga

        --
        /voodoo.css:
        #GeorgeWBush { position:absolute; bottom:-6ft; }
        1. wahsaga,

          danke für die negative Bewertung, hatte so lange keine mehr.
          Was war an meinem Beitrag nicht hilfreich?

          Was für einen Grund gab es an der Aussage des OP zu zweifeln, ausser,
          dass er das falsche Format hingeschrieben hat?

          Frank

          1. hi,

            danke für die negative Bewertung, hatte so lange keine mehr.

            Brauchst du'n Taschentuch? (Scheint dir ja doch recht nahe zu gehen ...)

            Was war an meinem Beitrag nicht hilfreich?

            Der Tonfall.
            Wieso fragst du dedlfix so blöd, ob er sich die positive Bewertung selber gegeben habe?
            Die war von mir, weil ich seine Antwort eben hilfreich fand.

            Was für einen Grund gab es an der Aussage des OP zu zweifeln, ausser,
            dass er das falsche Format hingeschrieben hat?

            Was für einen Grund gab es für dich, so darauf abzufahren, dass dedlfix von zwei widersprüchlichen Teilen der Aussage den evtl. vom OP gemeinten übersehen, und daher aus dem anderen schließend einen Ratschlag gegeben hat, der wirklich hilfreich für jemanden sein könnte, der sich mit den Möglichkeiten, Datumswerte in MySQL abzulegen, noch nicht beschäftigt hat ...?

            gruß,
            wahsaga

            --
            /voodoo.css:
            #GeorgeWBush { position:absolute; bottom:-6ft; }
            1. Wer ist denn worauf abgefahren?

              Warum ich dedlfix's Aussage für "nicht hilfreich" befunden habe, habe ich auch begründet. Was enthielt sie denn auch für einen praktischen Hinweis, die Abfrage entsprechend zu gestalten? Es war einfach ein Generalverweis auf Datentypen, mehr nicht. Was hätte dem OP die Verwendung vom richtigen Datentypen (den er vielleicht auch verwendet hat) effektiv geholfen? Masst du dir an, das zu beantworten bzw. einzuschätzen?

              Was war an meinem Tonfall falsch (darüber hinaus, was masst du dir an, dies zu beurteilen? Und was geht dich das an?)? Dass ich ihm gesagt habe, dass seine Antwort nicht hilfreich war? Dass ich ihn gefragt hab, ob er sich selbst dennoch selbst positiv bewertet hat? Keine Ahnung ob das geht (ich vermute mal schon, wenn ich so manche Antworten - unter anderem auch deine - durchlese), ist mir aber auch egal, weil ich sowas für mich nicht nötig habe.

              Warum unterstellst du dem OP Unwissenheit oder gar Dummheit, woher nimmst du deine Arroganz?

              Was hast du hilfreich bisher zur Frage beigetragen?

              [ ] viel
              [ ] etwas
              [ ] gar nichts

              Ich vermute, du wirst jetzt ganz gekonnt vielen oder gar jede der vorgenannten Fragen ausweichen und vielleicht sogar dieses Posting nochmal als negativ bewerten, damit du nochmal richtig deine Meinung zum Ausdruck bringen kannst. Lasse mich gern vom Gegenteil überzeugen.

              Adios, Frank

              1. hi,

                Dass ich ihn gefragt hab, ob er sich selbst dennoch selbst positiv bewertet hat? Keine Ahnung ob das geht (ich vermute mal schon, wenn ich so manche Antworten - unter anderem auch deine - durchlese), ist mir aber auch egal, weil ich sowas für mich nicht nötig habe.

                Und warum unterstellst du dann hier zum wiederholten Male anderen, dass sie dies nötig hätten?

                Warum unterstellst du dem OP Unwissenheit oder gar Dummheit, woher nimmst du deine Arroganz?

                Wo habe ich das denn bitte getan?

                gruß,
                wahsaga

                --
                /voodoo.css:
                #GeorgeWBush { position:absolute; bottom:-6ft; }
                1. wahsaga, ich bedaure zutiefst, dass du dich angesprochen fühlst.

                  Mehr möchte ich zu dem Thema nicht mehr sagen, du bist dafür kein fähiger und objektiver Gesprächspartner.

                  Warum unterstellst du dem OP Unwissenheit oder gar Dummheit, woher nimmst du deine Arroganz?

                  »»Wo habe ich das denn bitte getan?

                  In dem du bewusst überliesst, dass er angegeben hat, welchen Datentyp er verwendet hat und dich lieber daran aufziehst, dass er das falsche Format dahintergeschrieben hat (als wäre er zu blöd, zu wissen, dass das Format anders notiert wird).

                  Adios,
                  Frank

                  1. yo,

                    wahsaga, ich bedaure zutiefst, dass du dich angesprochen fühlst.

                    upss meinst du mich mit deinem post ?

                    Ilja

                    1. Hi,

                      nein, ich meine nicht dicht mit dem angesprochen fühlen.

                      Grüsse
                      Frank

                      1. Hallo,

                        nein, ich meine nicht dicht mit dem angesprochen fühlen.

                        Die meisten Beiträge in diesem Theard müssen in ein anderes Forum "Streit" verschoben werden :-D

                        Gruss
                        Alexander.

                        1. yo,

                          Die meisten Beiträge in diesem Theard müssen in ein anderes Forum "Streit" verschoben werden :-D

                          nah, selbst ein forum wie selfhtml ist neben dem fachlichen diskussionen auch immer eine ort, wo man all seinen gefühlen freien lauf lassen kann, eine menchlische schnittstelle, sozusagen multimedial ;-)

                          auf jeden fall hast du ja eine lösung für dein problem, den rest amchen die "experten" unter sich aus.....

                          Ilja

                  2. hi,

                    Warum unterstellst du dem OP Unwissenheit oder gar Dummheit, woher nimmst du deine Arroganz?
                    »»Wo habe ich das denn bitte getan?

                    In dem du bewusst überliesst, dass er angegeben hat, welchen Datentyp er verwendet hat und dich lieber daran aufziehst, dass er das falsche Format dahintergeschrieben hat (als wäre er zu blöd, zu wissen, dass das Format anders notiert wird).

                    Bist du zu blöd, mich zu verstehen, oder willst du es einfach nicht?

                    Ich habe lediglich darauf hingewiesen, dass dedlfix vermutlich auf Grund des "falschen" Formats übersehen haben könnte, dass der OP den Spaltentyp Date davor explizit erwähnt hatte, und wie er dann anschließend bestätigt hat, war's ja auch genau so.

                    Ich habe dem Fragesteller also überhaupt keine "Blödheit" unterstellt - und bei dir brauche ich mir die Mühe wohl nicht mehr machen, denn du beweist es ja langsam selber.

                    gruß,
                    wahsaga

                    --
                    /voodoo.css:
                    #GeorgeWBush { position:absolute; bottom:-6ft; }
                    1. yo,

                      Bist du zu blöd, mich zu verstehen, oder willst du es einfach nicht?

                      Ich habe dem Fragesteller also überhaupt keine "Blödheit" unterstellt - und bei dir brauche ich mir die Mühe wohl nicht mehr machen, denn du beweist es ja langsam selber.

                      der Tonfall Wahsaga, der Tonfall......

                      Ilja

            2. yo,

              Was war an meinem Beitrag nicht hilfreich?

              Der Tonfall.

              wer im glashaus sitzt, der sollte nicht mit steinen.....

              mal ehrlich, ich glaube das Franks kritik noch im rahmen hält, denke mal da war ein schuss ironie dabei und weniger eine persönliche ablenhung gegenüber dedlfix.

              Ilja

        2. Hallo,

          Das hinten stehende Muster passt jedenfalls nicht zu DATE, denn das Format dafür ist YYYY-MM-DD.

          Das stimmt und tut mir leid. Hier habe ich mich nach xx Stunden Arbeit vertippt. Es sollte 0000-00-00 heissen. Aber die Antworten sind auf jeden Fall da.

          Danke.
          Alexander.

      2. echo $begrüßung;

        Verwende eine Spalte vom Typ DATE.
        Hat er das nicht bereits getan

        Anreise und Abreise sind vom Typ Date - 00-00-0000

        Ah ja. Das Format war, weil es in der unsortierbaren Weise notiert war und nicht dem Systemdefault-Wert entspricht, auffälliger als das Wort Date, so dass ich letzteres überlas.

        Die Frage des OP richtet sich mehr auf das Problem, wie man mit einer
        Abfrage feststellt, dass sich zwei definierte Zeiträume überschneiden.

        BETWEEN war eigentlich auch das, was ich im Sinn hatte. Irgendjemand muss das in meinem Speicher nach der letzten Benutzung falsch abgelegt haben, so dass ich es fälschlicherweise mit den Datums- und Zeit-Funktionen verband. Ist natürlich Käse, da BETWEEN auch mit anderen Operanden als Zeit-Elementen arbeiten kann. Also wäre die Comparison Functions and Operators-Seite angebrachter gewesen.

        SELECT 1 FROM MeineTabelle
        WHERE @neuesAnreiseDatum NOT BETWEEN [Anreise] AND [Abreise] ...

        
        > Wenn NULL zurückkommt [...]  
          
        Erlaubst du zwei kleine Korrekturen? Feldnamen werden unter MySQL nicht ge-[]-klammert sondern ge`backtick`t (was man nur tun muss, wenn man reservierte Bezeichner oder bestimmte Sonderzeichen im Feldnamen verwendet). Wenn es keine Ergebnismenge gibt, gibt MySQL gar nichts zurück, noch nicht einmal NULL. Der Aufruf einer Fetch-Funktion liefert dann einen Statuswert, der aussagt, dass keine (weiteren) Reihen verfügbar sind.  
          
          
        echo "$verabschiedung $name";
        
        1. Hi dedlfix,

          deine Korrekturen sind gern angenommen, ich kenne mich mit MySQL-Spezifika nicht aus. Das []-einklammern mache ich aus Gewohnheit.

          Du hast Recht, statt NULL sollte gar nichts zurückkommen.

          Jeder macht mal Fehler ;)

          Gut Nacht, Frank

      3. yo,

        SELECT 1 FROM MeineTabelle
        WHERE @neuesAnreiseDatum NOT BETWEEN [Anreise] AND [Abreise]
        AND   @neuesAbreiseDatum NOT BETWEEN [Anreise] AND [Abreise]
        AND /* ... weitere vergleiche für z.b. dasselbe Mietobjekt */

          
        zu den korrekturen, die dedlfix schon gesagt hat, kommt noch hinzu, dass BETWEEN der falsche Operator ist und du falsche aussagen bekommst. besser wäre:  
          
        ~~~sql
          
        SELECT "schon gebucht", Anreise, Abreise  
        FROM MeineTabelle  
        WHERE @neuesAnreiseDatum <= Abreise  
        AND   @neuesAbreiseDatum >= Anreise  
        AND /* ... weitere vergleiche für z.b. dasselbe Mietobjekt */  
        
        

        Ilja

        1. Hallo,

          WHERE @neuesAnreiseDatum <= Abreise
          AND   @neuesAbreiseDatum >= Anreise
          AND ....

          Das würde nicht funktionieren. Stell dir mal folgende vor:

          Vorhanden:
          Anreise: 2006-02-10
          Abreise: 2006-02-20

          Neu:
          Anreise: 2006-02-05
          Abreise: 2006-02-25

          Man muss da mehr prüfen. So wird das gelöst (Obwohl mir diese Lösung nicht so gefällt):

          ...
          WHERE @neuAnreise NOT BETWEEN anreise AND abreise
          AND   @neuAbreise NOT BETWEEN anreise AND abreise
          AND    anreise    NOT BETWEEN @neuAnreise AND @neuAbreise
          AND    abreise    NOT BETWEEN @neuAnreise AND @neuAbreise

          Vielleicht findet sich eine Methode, wo man direkt prüfen kann ob sich 2 Zeitperioden überschneiden :-) Abstrakt so: SELECT X FROM Y

          WHERE anreise AND abreise
          NOT BETWEEN @neuAnreise AND @neuAbreise.

          Das wäre meiner Meinung nach perfekt. Ich bin aber noch am Suchen.

          Das wäre interessant.
          Alexander.

          1. yo,

            WHERE @neuesAnreiseDatum <= Abreise
            AND   @neuesAbreiseDatum >= Anreise

            Das würde nicht funktionieren. Stell dir mal folgende vor:

            Vorhanden:
            Anreise: 2006-02-10
            Abreise: 2006-02-20

            Neu:
            Anreise: 2006-02-05
            Abreise: 2006-02-25

            hast du query mal ausprobiert ?

            ich kann nicht sehen, dass mit deinen daten meine Abfrage das nicht als schon gebucht erkennen würde. meine bedingungen:

            1. @neuesAnreiseDatum <= Abreise wäre 2006-02-05 <= 2006-02-20

            2. @neuesAbreiseDatum >= Anreise wäre 2006-02-25 >= 2006-02-10

            und meiner meindung sind da beide Aussagen wahr oder sehe ich da jetzt den wald vor lauter bäumen nicht mehr ? kann durchaus sein, manchmal bin ich einfach ein wenig blind. aber vielleicht schauchst du dir die beiden aussagen noch mal an.

            ich würde nicht mit BETWEEN arbeiten, das ist meiner meinung nach kein guter weg.

            Ilja

            1. Hallo,

              Vorher habe ich Dich nicht ganz richtig verstanden. Sorry.
              Die Aussage soll, nach der Überprüfung doch korrekt sein.

              Also, wenn beide Teile wahr sind, dann ist der Zeitraum belegt.

              Danke.
              Alexander.

        2. Hi Ilja,

          wieso ist BETWEEN ein falscher Operator für Datumswerte? Das wäre mir sehr neu.

          Welche falschen Aussagen bekomme ich denn? Ich habe mir gerade die Zeit genommen, das Szenario mal nachzustellen. BETWEEN funktioniert für Datumswerte wunderbar und die Abfragesemantik deckt genau das Problem ab. Du stellst die Frage einfach nur aus der Gegenrichtung.

            
          create table datumsTest  
          (  
           Id int Identity(1,1) PRIMARY KEY,  
           Anreise datetime NOT NULL,  
           Abreise datetime NOT NULL  
          )  
            
          INSERT datumsTest (Anreise, Abreise) VALUES ('2006-01-14', '2006-01-18')  
          INSERT datumsTest (Anreise, Abreise) VALUES ('2006-02-21', '2006-02-23')  
            
          DECLARE @planAnreise datetime  
          DECLARE @planAbreise datetime  
            
          SET @planAnreise = '2006-01-19'  
          SET @planAbreise = '2006-02-12'  
            
          -- meins  
          SELECT 'noch frei', Id FROM datumsTest  
          WHERE (@planAnreise NOT BETWEEN Anreise AND Abreise)  
          AND (@planAbreise NOT BETWEEN Anreise AND Abreise)  
            
          -- deins  
          SELECT 'schonGebucht', Id FROM datumsTest  
          WHERE (@planAnreise <= Abreise)  
          AND (@planAbreise >= Anreise)  
          
          

          Die Ausführungspläne unterscheiden sich etwas, was je nach DBMS marginale Performance-Verbesserungen bringen könnte.

          Was sagst du?

          Ciao, Frank

          1. yo,

            wieso ist BETWEEN ein falscher Operator für Datumswerte? Das wäre mir sehr neu.

            BETWEEN prüft ob ein punkt (ein wert) innerhalb einem Wertebereich liegt. was wir hier haben sind aber zwei zeitbereiche, die auf schnittmengen überprüft werden.
            Ilja

            Welche falschen Aussagen bekomme ich denn?

            zum einen kannst du deine Abfrage nicht mit noch frei als Rückgabe bestätigen lassen, weil für einen Datensatz könnte sie frei sein, für einen anderen datensatz schon nicht mehr. das wird deutlich, wenn man mehrere zeitwerte in der tabelle zu stehen hat, nämlich einen der nicht überlagert und einen der überlagert.

            zum anderen müsstest du mit BETWEEN alle möglichkeien (kombinatorik) durchgehen und mit OR verknüpfen. Ein Beispiel wenn deine query fälschlicherweise frei anzeigen würde wäre:

            neuer_startwert < alter_startwert und neuer_endwert > alter_endwert

            damit wären beide neue Werte nicht zwischen den alten werten, trotzdem überlagern sich die zeiträume.

            Ilja

            1. Hallo Ilja,

              danke für den Hinweis, habe es eben selber nachvollziehen können.
              Ist mir leider durch die Lappen gegangen.

              Mit dir kann man aber glücklicherweise vernünftig kommunizieren.

              Danke, ciao, Frank