Milchiz: SQL Probleme eine bestimmte Zeitperiode auszugeben

Ich muss in einer SQL Abfrage alle Personen ausgeben, die im Monat September einen Parkplatz gemietet haben. Es gibt einen Mietanfang und ein Mietende, die man individuell setzen kann.

Ein paar Daten als Beispiel:
+-------+---------+------------+------------+
¦ Name  ¦ Vorname ¦ MietBeginn ¦ MietEnde   ¦
+-------+---------+------------+------------+
¦ Meier ¦ Franz   ¦ 2010-12-22 ¦ 2011-11-17 ¦
+-------+---------+------------+------------+
¦ Peter ¦ Hans    ¦ 2011-09-25 ¦ 2011-09-25 ¦ //Nur einen Tag
+-------+---------+------------+------------+

Die Situation auf einer Zeitlinie:

(Gesucht: Alle, die im September einen Parkplatz mieten)
                                 /

------
(MietDauer)

Ich habe schon verzweifelt mit verschiedenen "WHERE/BETWEEN Klauseln" versucht auf die Lösung zu kommen, jedoch vergeblich. Ich hoffe ihr könnt mir weiterhelfen. Danke :)

  1. Ich habe schon verzweifelt mit verschiedenen "WHERE/BETWEEN Klauseln" versucht auf die Lösung zu kommen, jedoch vergeblich. Ich hoffe ihr könnt mir weiterhelfen. Danke :)

    Probieren ist ja ganz gut, nachlesen manchmal besser:
    http://dev.mysql.com/doc/refman/5.1/de/date-and-time-functions.html

  2. Hi!

    Ich muss in einer SQL Abfrage alle Personen ausgeben, die im Monat September einen Parkplatz gemietet haben. Es gibt einen Mietanfang und ein Mietende, die man individuell setzen kann.

    Definiere bitte "im Monat X". Sollen nur komplett enthaltene Mieten abgefragt werden oder solche, die vor dem gewünschten Zeitraum beginnen oder nach ihm enden oder den gesamten Monat beinhalten oder Kombinationen davon?

    Ich habe schon verzweifelt mit verschiedenen "WHERE/BETWEEN Klauseln" versucht auf die Lösung zu kommen, jedoch vergeblich. Ich hoffe ihr könnt mir weiterhelfen. Danke :)

    Zunächst muss man die Bedingungen in normalsprachlicher Weise exakt formulieren. Dann kann man schauen, welche Funktionen bei der Umsetzung helfen.

    Lo!

    1. Definiere bitte "im Monat X". Sollen nur komplett enthaltene Mieten abgefragt werden oder solche, die vor dem gewünschten Zeitraum beginnen oder nach ihm enden oder den gesamten Monat beinhalten oder Kombinationen davon?

      Es sollen auch Mieten abgefragt werden, die nicht den gesamten Monat beinhalten. In der Ausgabe sollten alle Personen vorhanden sein, die im Monat X mindestens einen Tag lang einen Parkplatz mieten.

      1. Hi!

        Es sollen auch Mieten abgefragt werden, die nicht den gesamten Monat beinhalten. In der Ausgabe sollten alle Personen vorhanden sein, die im Monat X mindestens einen Tag lang einen Parkplatz mieten.

        "Mindestens einen Tag lang" ist zu ungenau. Du hast die vier Werte Mietbeginn, Mietende, Monatsanfang und Monatsende. Diese müssen in der Formulierung der Bedingung enthalten sein. Der Mietbeginn kann zwar vor dem September liegen, aber nicht danach. Das Mietende kann nach dem Monatsende liegen, aber nicht vor Monatsanfang. Falsche Einträge mit einem Mietbeginn nach dem Mietende setze ich mal als nichtexistent voraus. Zusammengekürzt ergibt sich, dass der Mietbeginn vor dem Monatsende liegen muss _und_ das Mietende nach dem Monatsanfang. Und mit dieser Ausformulierung kann man wesentlich einfacher den zugehörigen Code finden.

        Lo!

        1. Zusammengekürzt ergibt sich, dass der Mietbeginn vor dem Monatsende liegen muss _und_ das Mietende nach dem Monatsanfang. Und mit dieser Ausformulierung kann man wesentlich einfacher den zugehörigen Code finden.

          Das Mietende kann auch genau der Monatsanfang sein, wenn zum Beispiel jemand einen Parkplatz vom 2011-09-01 bis 2011-09-01 mietet. Danke schonmal für die exakte Formulierung!

          Ich habe es mal versucht in SQL umzuschreiben:

          WHERE MietBeginn BETWEEN '2000-01-01' AND '2011-09-31'
          AND MietEnde BETWEEN '2011-09-01' AND '3000-01-01'

          Wenn ich das so versuche bekomme ich folgende Meldung: "Fehler beim Konvertieren einer Zeichenfolge in ein Datum und/oder eine Uhrzeit."

          Es liegt wahrscheinlich daran, dass ich nicht einfach so zwei BETWEEN's verwenden kann :(

          1. Es liegt wahrscheinlich daran, dass ich nicht einfach so zwei BETWEEN's verwenden kann :(

            Es liegt an der riesigen SQL Wissenslücke... Streng genommen musst du nur das Datumsfeld auslesen und schauen, ob der Monat September enthalten ist. BOOMM , treffer, versenkt.

            Refenrenz lesen, verstehen, umsetzen. Denn die exakte SQL Abfrage ist wirklich einfach. Aber es ist wichtig, dass du selbst auf die richtige Syntax kommst damit du daraus lernst.

            1. Hi!

              Es liegt wahrscheinlich daran, dass ich nicht einfach so zwei BETWEEN's verwenden kann :(
              Es liegt an der riesigen SQL Wissenslücke... Streng genommen musst du nur das Datumsfeld auslesen und schauen, ob der Monat September enthalten ist. BOOMM , treffer, versenkt.

              So einfach ist das nicht. Ich kenne keine MySQL-Funktion, die ein Überschneiden von Zeiträumen ermittelt. Also muss man die jeweiligen Grenzen zu Fuß überprüfen. Du hast zwei Zeiträume, die sich teilweise am Anfang oder am Ende überschneiden können, bei denen einer vollständig im anderen und umgekehrt liegen kann oder bei denen keine Überschneidung stattfindet. Alle diese Gegebenheiten müssen berücksichtigt werden. Jedoch kann man das mit zwei Vergleichen abhandeln, man muss nur darauf kommen, weil die Logik auf den ersten Blick ein wenig verkehrt herum aussieht.

              Lo!

              1. Hi!

                So einfach ist das nicht. Ich kenne keine MySQL-Funktion, die ein Überschneiden von Zeiträumen ermittelt. Also muss man die jeweiligen Grenzen

                Es wurde doch gesagt, dass es egal ist ob sich etwas überschneidet oder nicht. Denn sobald auch nur ein Tag im September gemietet wurde soll der Datensatz auftauchen. Egal ob im Monat vorher begonnen oder im Monat darauf geendet. Innerhalb September gemietet ist somit doch eindeutig.

                1. Hi!

                  Es wurde doch gesagt, dass es egal ist ob sich etwas überschneidet oder nicht. Denn sobald auch nur ein Tag im September gemietet wurde soll der Datensatz auftauchen. Egal ob im Monat vorher begonnen oder im Monat darauf geendet. Innerhalb September gemietet ist somit doch eindeutig.

                  Mein Fehler. Habs jetzt erst gesehen

                  22.08.2011 - 22.10.2011 Frei Eingabe, nicht jeder Monat wird erfasst. Ok. Also größer bzw. kleiner als

                2. Hi!

                  So einfach ist das nicht. Ich kenne keine MySQL-Funktion, die ein Überschneiden von Zeiträumen ermittelt. Also muss man die jeweiligen Grenzen

                  Es wurde doch gesagt, dass es egal ist ob sich etwas überschneidet oder nicht. Denn sobald auch nur ein Tag im September gemietet wurde soll der Datensatz auftauchen. Egal ob im Monat vorher begonnen oder im Monat darauf geendet. Innerhalb September gemietet ist somit doch eindeutig.

                  Ich könnte den Monat des MietBeginns und vom MietEnde ausgeben und dann nachsehen ob z.B. der Monat 09 (September) dazwischen liegt. Von dieser Lösung will ich aber absehen, da sie einfach unelegant ist.

          2. Hi!

            Zusammengekürzt ergibt sich, dass der Mietbeginn vor dem Monatsende liegen muss _und_ das Mietende nach dem Monatsanfang. Und mit dieser Ausformulierung kann man wesentlich einfacher den zugehörigen Code finden.

            Das Mietende kann auch genau der Monatsanfang sein, wenn zum Beispiel jemand einen Parkplatz vom 2011-09-01 bis 2011-09-01 mietet.

            Der Monats- und Mietanfang ist 0 Uhr, das Monats- und Mietende ist immer 23:59:59. Die Uhrzeiten musst du mit berücksichtigen oder für das Mietende immer einen Tag später nehmen (+ INTERVAL 1 DAY). Wenn der erste Tag gemietet wurde, ist - mit Beachtung der Uhrzeit - der Beginn 0 Uhr vor dem Mietende 23:59. Beim addierten Tag ist es vergleichbar.

            Danke schonmal für die exakte Formulierung!

            Bitte, aber du hast sie nicht so umgesetzt.

            Ich habe es mal versucht in SQL umzuschreiben:
            WHERE MietBeginn BETWEEN '2000-01-01' AND '2011-09-31'
            AND MietEnde BETWEEN '2011-09-01' AND '3000-01-01'

            Ich sagte nicht "von-bis" sondern ein "größer als" und ein "kleiner als"

            Wenn ich das so versuche bekomme ich folgende Meldung: "Fehler beim Konvertieren einer Zeichenfolge in ein Datum und/oder eine Uhrzeit."
            Es liegt wahrscheinlich daran, dass ich nicht einfach so zwei BETWEEN's verwenden kann :(

            Doch, das kannst du schon. Es führt im schlimmsten Fall zu nicht oder falsch gewählten Datensätzen. Das Problem könnte aber ein schlecht gewählter Feldtyp sein. Hast du für die Datenfelder einen Stringtyp oder DATE/DATETIME genommen?

            Lo!

            1. »»Hast du für die Datenfelder einen Stringtyp oder DATE/DATETIME genommen?

              DATE

              1. Hi!

                Hast du für die Datenfelder einen Stringtyp oder DATE/DATETIME genommen?
                DATE

                Dann sollte es eigentlich gehen. Der September hat aber nur 30 Tage, vielleicht liegt es daran. Da du sowieso nur Tage zur Verfügung hast, kannst du die Uhrzeit weglassen und dir Plus-1-Tag-Variante nehmen und den Abfragezeitraumbeginn als 'Jahr-Monat-01' und das Ende als 'Jahr-Monat-01' + INTERVAL 1 MONTH schreiben. Das klappt auch über einen Jahreswechsel hinaus.

                Lo!

                1. Es lag daran und es funktioniert jetzt alles :). Danke vielmals für den Lösungsansatz, ich stand echt auf dem Schlauch :P

                  WHERE MietBeginn < '2011-10-01' AND MietEnde > '2011-09-01'

                  So erstmal ausprobiert und hat funktioniert.

                  »»Abfragezeitraumbeginn als 'Jahr-Monat-01' und das Ende als 'Jahr-Monat-01' + INTERVAL 1 MONTH schreiben. Das klappt auch über einen Jahreswechsel hinaus.

                  1. Abfragezeitraumbeginn als 'Jahr-Monat-01' und das Ende als 'Jahr-Monat-01' + INTERVAL 1 MONTH schreiben. Das klappt auch über einen Jahreswechsel hinaus.

                    Der INTERVAL 1 MONTH müsste doch beim MietBeginn sein und nicht beim Ende, weil der 1 Monat mehr hat. Oder verstehe ich das falsch ?

                    1. Abfragezeitraumbeginn als 'Jahr-Monat-01' und das Ende als 'Jahr-Monat-01' + INTERVAL 1 MONTH schreiben. Das klappt auch über einen Jahreswechsel hinaus.

                      Der INTERVAL 1 MONTH müsste doch beim MietBeginn sein und nicht beim Ende, weil der 1 Monat mehr hat. Oder verstehe ich das falsch ?

                      Soll bedeuten:
                      In deinem Fall ist ja das Ende des Zeitraums 01.10.2011. Nur das du es in der Abfrage anders formulierst. Du sagst ja
                      MietBeginn < '2011-10-01'

                      Mietbeginn kleiner dem 01.10. Bedeutet ja das du nur bis zum 01.10 berücksichtigst und somit das dein Endtermin ist. Auch wenn du diesen Zeitraum bei Mietbeginn abfragst ;) Das meinte mein Vorredner mit
                      "...weil die Logik auf den ersten Blick ein wenig verkehrt herum aussieht..."

                    2. Hi!

                      Abfragezeitraumbeginn als 'Jahr-Monat-01' und das Ende als 'Jahr-Monat-01' + INTERVAL 1 MONTH schreiben. Das klappt auch über einen Jahreswechsel hinaus.
                      Der INTERVAL 1 MONTH müsste doch beim MietBeginn sein und nicht beim Ende, weil der 1 Monat mehr hat. Oder verstehe ich das falsch ?

                      _Miet_beginn und -ende stehen in den jeweiligen Feldern. Ich nehme an, dass du den September nur als Beispielmonat gewählt hast, ansonsten jeden beliebigen Monat abzufragen gedenkst. Dann musst du _Abfrage_beginn und -ende errechnen und kannst aus dem abzufragenden Jahr und Monat zuzüglich 01 für den Tag den Monatsanfang bilden und aus diesem mit + INTERVAL 1 MONTH das Monatsende finden. Für wirklich nur eine (händische) Abfrage auf einen Monat kannst du natürlich feste Daten nehmen.

                      Lo!

                  2. Mahlzeit Milchiz,

                    WHERE MietBeginn < '2011-10-01' AND MietEnde > '2011-09-01'

                    So erstmal ausprobiert und hat funktioniert.

                    ... ist aber trotzdem falsch:

                    Angenommen, ich habe vom 01.08.2011 bis einschließlich 01.09.2011 gemietet - dann würde ich nicht berücksichtigt. Der Mietbeginn ist zwar kleiner als der 01.10.2011, aber das Mietende ist genau der 01.09.2011 ... und Du fragst auf "größer als" ab - nicht auf "größer gleich".

                    Oder verstehst Du unter "Mietende am 01.09.2011" = 01.09.2011 0:00 Uhr?

                    MfG,
                    EKKi

                    --
                    sh:( fo:| ch:? rl:( br:& n4:~ ie:% mo:} va:) de:] zu:) fl:{ ss:) ls:& js:|
                    1. Hi!

                      WHERE MietBeginn < '2011-10-01' AND MietEnde > '2011-09-01'
                      So erstmal ausprobiert und hat funktioniert.
                      ... ist aber trotzdem falsch:

                      Stimmt, geht quasi auf mein Konto. Beim Tagesvergleich muss es Mietende >= Abfrageanfang und Mietbeginn < Abfrageanfang + 1 Monat sein.

                      Lo!

      2. Hallo,

        CROSS JOIN aus Liste aller Mieter und Liste aller Monate (also Monat+Jahr, zb. in der Form: 201108 -> schoene Integerzahl) kombiniert mit WHERE EXISTS (SELECT WHERE Mieter ... and Monat .... )

        Ergebnis sieht dann so aus

        Mieter (kommt aus der Liste aller Mieter)
        Monat (kommt aus der Liste aller Monate)

        Wenn Datensatz in der Ausgabe, dann hat der Mieter in dem Monat einen Parkplatz gemietet, ansonsten nicht. Alternativ kannst du mit einem LEFT OUTER JOIN arbeiten und auf NULL pruefen.

        Gruss, Frank