Hans S.: In MySQL timestamp nach Jahr suchen

Ich speichere in meiner MySQL tabelle das Datum per VARCHAR(20) im Timestamp.

Jetzt würde ich gerne in meiner MySQL Abfrage nur dort selektieren, wo das Jahr 2008 ist.

Wie ginge das?

  1. Hi,

    Ich speichere in meiner MySQL tabelle das Datum per VARCHAR(20) im Timestamp.

    Das ist eine Dummheit.

    Jetzt würde ich gerne in meiner MySQL Abfrage nur dort selektieren, wo das Jahr 2008 ist.

    Stelle dein Datenmodell auf einen der Datumstypen von MySQL um - dann kannst du beim Selektieren ganz einfach die Funktion YEAR() darauf anwenden.

    MfG ChrisB

    --
    „This is the author's opinion, not necessarily that of Starbucks.“
  2. echo $begrüßung;

    Ich speichere in meiner MySQL tabelle das Datum per VARCHAR(20) im Timestamp.

    Eine schlechte Idee.

    Jetzt würde ich gerne in meiner MySQL Abfrage nur dort selektieren, wo das Jahr 2008 ist.
    Wie ginge das?

    Ich nehme an, der Timestamp ist ein Unix-Timestamp, kein MySQL-Timestamp. Dann musst du zuerst einen Datumswert errechnen FROM_UNIXTIME(), von dem du dann das YEAR() ermitteln kannst.

    Doch selbst wenn das Feld von einem der Datumstypen ist und man dann WHERE YEAR(feld) = $jahr nehmen könnte, wäre das nicht sehr performant, weil diese Rechnung für jede Zeile ausgeführt werden muss und dafür kein Index verwendet werden kann. Besser ist es, einen Index auf dem Datumsfeld zu haben und dann BETWEEN zu verwenden:

    ... WHERE feld BETWEEN MAKEDATE($jahr, 1) AND LAST_DAY(MAKEDATE($jahr, 365))

    Besser hab ich es nicht hinbekommen, aber das sieht schlimmer aus, als es ist. Die beiden Argumente von BETWEEN werden nämlich nur ein einziges Mal berechnet und die Ergebnismenge kann nun effizient über den Index eingeschränkt werden. Man kann das sehr schön mit EXPLAIN verfolgen.

    echo "$verabschiedung $name";

    1. Ok, danke. Glücklicherweise habe ich noch nicht die Daten eingetragen, kann also jetzt noch alles ändern.

      Timestamp scheint ja immer den aktuellen nehmen zu wollen, dann werde ich wohl DATETIME nehmen. Wie würde ich denn dort dieses eingeben, wenn ich Tag, Stunde, Minute, Jahr etc. per einzelnen Dropdowns auswählen wollen würde?

      Etwa:
      '.$year.'-'.$month.'-'.day.' '.$hour.':'.$minute.':'.$seconds.'

      1. echo $begrüßung;

        Wie würde ich denn dort [DATETIME-Feld] dieses eingeben, wenn ich Tag, Stunde, Minute, Jahr etc. per einzelnen Dropdowns auswählen wollen würde?
        Etwa: '.$year.'-'.$month.'-'.day.' '.$hour.':'.$minute.':'.$seconds.'

        Kaum, denn diese Werte stehen einerseits in $_GET oder $_POST, andererseits sind sie Usereingaben und nicht ungeprüft/unbehandelt zu übernehmen.

        $datetimestring = sprintf('%04s-%02s-%02s %02s:%02s:%02s',
            intval($_POST['year']),
            intval($_POST['month']),
            intval($_POST['day']),
            intval($_POST['hour']),
            intval($_POST['minute']),
            intval($_POST['seconds']));

        Damit entstehen zwar unter Umständen ungültige Datumswerte, die gegebenenfalls mit einer MySQL-Warnung quittiert werden, aber es ist nicht weiter schädlich. Eine inhaltliche Prüfung kann mit checkdate() und für die Zeit recht einfach zu Fuß vorgenommen werden.

        echo "$verabschiedung $name";

        1. Kaum, denn diese Werte stehen einerseits in $_GET oder $_POST, andererseits sind sie Usereingaben und nicht ungeprüft/unbehandelt zu übernehmen.

          Ich dachte dann auch eher so, dass ich vorher die Werte in eine Variable schreibe:
          $year = mysql_real_escape_string($_POST['jahr']);
          Sollte das nicht auch gehen?

          1. echo $begrüßung;

            Kaum, denn diese Werte stehen einerseits in $_GET oder $_POST, andererseits sind sie Usereingaben und nicht ungeprüft/unbehandelt zu übernehmen.
            Ich dachte dann auch eher so, dass ich vorher die Werte in eine Variable schreibe:
            $year = mysql_real_escape_string($_POST['jahr']);
            Sollte das nicht auch gehen?

            Das wäre dann ein meinem intval()-Vorschlag ähnelnder Ansatz. Vor SQL-Injection sicher, aber genauso unsicher gegen unsinnige Werte. Außerdem legst du extra Variablen an, die du ansonsten nicht weiter verwendest. Mit sprintf() kannst du dir diesen Zwischenschritt schenken.

            echo "$verabschiedung $name";

            1. Die Werte würden ja eh aus einer Dropdown Liste kommen, wodurch ja dann unsinnige Werte eigentlich vermieden sein müssten.

              Wenn ich jetzt in der MySQL Tabelle ein DATETIME-Feld habe, wie kann ich dann zum Beispiel nur Jahr, Monat und Tag ausgeben?

              1. Hallo

                Die Werte würden ja eh aus einer Dropdown Liste kommen, wodurch ja dann unsinnige Werte eigentlich vermieden sein müssten.

                Nein, denn du kannst das HTML-Formular bei dir abspeichern, die Struktur des Formulars ändern und auf diese Weise unerwartete Werte erzeugen.

                Wenn ich jetzt in der MySQL Tabelle ein DATETIME-Feld habe, wie kann ich dann zum Beispiel nur Jahr, Monat und Tag ausgeben?

                Wie wär's denn mal mit lesen? dedlfix hat in seinem ersten Posting in diesem Thread am Beispiel "Vergleich der Jahre" analoges bereits erklärt. Dort findest du auch die Links in den Datums-und-Zeit-Teil der MySQL-Doku (von ihm nach lang=en, von mir jetzt in lang=de). Für diese Fragestellung wird es ab DATE_FORMAT interessant.

                Tschö, Auge

                --
                Die deutschen Interessen werden am Liechtenstein verteidigt.
                Veranstaltungsdatenbank Vdb 0.2
              2. echo $begrüßung;

                Die Werte würden ja eh aus einer Dropdown Liste kommen, wodurch ja dann unsinnige Werte eigentlich vermieden sein müssten.

                Es gibt auch uneigentliche Clients. Die Art der Formulardarstellung an normalen Clients hat keinen direkten Einfluss auf die übermittelbaren Werte. Ein Request kann beliebige Parameter und -inhalte übermitteln.

                Wenn ich jetzt in der MySQL Tabelle ein DATETIME-Feld habe, wie kann ich dann zum Beispiel nur Jahr, Monat und Tag ausgeben?

                Wenn du es sofort ausgeben willst, lass es von einer passenden DateTime-Funktion MySQLs formatieren. Wenn du es unter PHP mit den herkömmlichen Funktionen (wie date()) weiterverarbeiten willst und außerdem nur Daten zwischen 1970 und 2038 vorkommen, ist ein Unix-Timestamp angebracht, den dir eine der MySQL-Funktionen liefern kann. Die neuere DateTime-Klasse PHPs kann hingegen mit Werten in der MySQL-Default-Formatierung gefüttert werden.

                echo "$verabschiedung $name";

                1. Hi,

                  Die neuere DateTime-Klasse PHPs kann hingegen mit Werten in der MySQL-Default-Formatierung gefüttert werden.

                  strtotime() uebrigens genauso.

                  MfG ChrisB

                  --
                  „This is the author's opinion, not necessarily that of Starbucks.“
                2. Es gibt auch uneigentliche Clients. Die Art der Formulardarstellung an normalen Clients hat keinen direkten Einfluss auf die übermittelbaren Werte. Ein Request kann beliebige Parameter und -inhalte übermitteln.

                  Das ist gut zu wissen, wusste ich nämlich noch nicht. Reicht das dann aus die Variabel per sprintf so zu besetzen, oder muss man dann noch eine if-Prüfung vornehmen?

                  1. echo $begrüßung;

                    Reicht das dann aus die Variabel per sprintf so zu besetzen, oder muss man dann noch eine if-Prüfung vornehmen?

                    Eine Datum unterliegt ein paar mehr Regeln als der Formatierung. Darauf ging ich ja schon ein und erwähnte dabei auch checkdate().

                    echo "$verabschiedung $name";