ha-bauer: datetime- String formatieren

Hallo zusammen,

ich habe eine kleine Frage bezüglich PHP und mySQL.

Ich habe in der Datenbank einige Blogeinträge. Für ein Archiv will ich nun verschiedene Links erzeugen, die jeweils einen Monat (im Format "MONTH YEAR") repräsentieren; auf Klick sollen darauf alle Einträge dieses Monats erscheinen.

Meine Frage ist nun: Wie schaffe ich es, aus einem String, der im mySQL- Format datetime vorliegt, nur den Monat und das Jahr zu extrahieren und diese im Format "August 2009" (zum Beispiel) auszugeben? Diese Links sollen dabei jedoch nur einmal pro Monat vorliegen, selbst wenn mehrere Einträge vom Monat August 2009 vorliegen.

Ich hoffe, ihr versteht, worauf ich hinaus will.

Danke für jede Antwort und viele Grüße,

ha-bauer

  1. Moin

    Du schaffst es mittels den MySQL-date und time Funktionen ein Datum formatiert auszugeben. Dazu eine kleine Function in PHP die englische in deutsche Monatsnamen tauscht und schon bekommst du diese.

    Damit die Daten "gruppiert" werden nutze die SQL-Anweisung: GROUP BY

    Gruß Bobby

    --
    -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
    ### Henry L. Mencken ###
    -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
    ## Viktor Frankl ###
    ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
    1. Moin

      Du schaffst es mittels den MySQL-date und time Funktionen ein Datum formatiert auszugeben. Dazu eine kleine Function in PHP die englische in deutsche Monatsnamen tauscht und schon bekommst du diese.

      Hi Bobby,

      danke schonmal für die Antwort. Leider bin ich, was SQL angeht, noch relativ unerfahren. Könntest du mir sagen, wie ich die Abfrage formulieren könnte?

      Vielen Dank,
      ha-bauer

      1. Moin

        danke schonmal für die Antwort. Leider bin ich, was SQL angeht, noch relativ unerfahren. Könntest du mir sagen, wie ich die Abfrage formulieren könnte?

        Dann hast du dir meine verlinkte Seite nicht richtig durchgelesen. Probiere bitte erst die Beispiele und poste dann wenn dies nicht funktioniert, wie du es probiert hast. Dann kann ich dir weiterhelfen. Auf der verlinkten Seite stehen viele Beispiele. Versuchs bitte erstmal selbst.

        Ein kleiner Hinweis sei gewährt: SELECT "Felder mit Date-Time-Funktion formatiert" FROM TABLE

        So in der Art muss dann dein Ergebnis aussehen.

        Gruß Bobby

        --
        -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
        ### Henry L. Mencken ###
        -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
        ## Viktor Frankl ###
        ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
        1. Dann hast du dir meine verlinkte Seite nicht richtig durchgelesen. Probiere bitte erst die Beispiele und poste dann wenn dies nicht funktioniert, wie du es probiert hast. Dann kann ich dir weiterhelfen. Auf der verlinkten Seite stehen viele Beispiele. Versuchs bitte erstmal selbst.

          Ein kleiner Hinweis sei gewährt: SELECT "Felder mit Date-Time-Funktion formatiert" FROM TABLE

          Hi nochmal,

          ich habe es bei den Beispielen mal mit EXTRACT(MONTH FROM '1999-07-02') probiert. Hat auch prima funktioniert, aber als ich dann statt '1999-07-02' meine Spalte 'post_date' angegeben hatte (EXTRACT(MONTH FROM 'post_date')), hat sich mySQL geweigert, mir ein Ergebnis zu liefern. Was mache ich da falsch? Und wie bekomme ich die Gruppierung hin? Da bin ich auch noch nicht hinter gekommen, trotz probierter Beispiele.

          Viele Grüße,
          ha-bauer

          1. Moin

            Hat auch prima funktioniert, aber als ich dann statt '1999-07-02' meine Spalte 'post_date' angegeben hatte (EXTRACT(MONTH FROM 'post_date')), hat sich mySQL geweigert, mir ein Ergebnis zu liefern. Was mache ich da falsch?

            Hast du das exact so geschrieben? versuchs mal ohne den Hochkommas.

            Und wie bekomme ich die Gruppierung hin? Da bin ich auch noch nicht hinter gekommen, trotz probierter Beispiele.

            Was hast du da genau probiert?

            Beachte bitte auch den Tip von "tk". Der ist Gold wert.

            Gruß Bobby

            --
            -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
            ### Henry L. Mencken ###
            -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
            ## Viktor Frankl ###
            ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
            1. Hast du das exact so geschrieben? versuchs mal ohne den Hochkommas.

              Danke, jetzt funktioniert's. Jetzt bekomme ich eine Menge Zahlen zurück. Kann ich die mit mySQL auch noch in die Monatsnamen umwandeln oder soll ich das mit einem PHP- Array erledigen?

              Was hast du da genau probiert?

              SELECT EXTRACT(MONTH FROM post_date) GROUP BY post_date
              Kleine Frage: Schaffe ich es irgendwie, innerhalb einer Abfrage sowohl den Monat als auch das Jahr zu extrahieren? YEAR_MONTH gibt mir ja das Jahr und den Monat ohne Leerzeichen zurück.

              Beachte bitte auch den Tip von "tk". Der ist Gold wert.

              Ich will erst mal den Hauptteil der Abfrage hinbekommen. Dann kann ich mich um die Eindeutschung kümmern.

              Viele Grüße,
              ha-bauer

              1. Hi,

                SELECT EXTRACT(MONTH FROM post_date) GROUP BY post_date
                Kleine Frage: Schaffe ich es irgendwie, innerhalb einer Abfrage sowohl den Monat als auch das Jahr zu extrahieren?

                Kleine Gegenfrage: Schaffst du es sonst, den Inhalt von mehr als nur einer Spalte zu selektieren? (Nein, SELECT * gilt hier nicht als positive Antwort.)

                Warum du dich übrigens für EXTRACT entschieden hast, ist mir unverständlich.
                Es gibt doch extra Funktionen, die wie Monat und Jahr auf Englisch heissen.

                MfG ChrisB

                --
                Light travels faster than sound - that's why most people appear bright until you hear them speak.
                1. Hi,

                  SELECT EXTRACT(MONTH FROM post_date) GROUP BY post_date
                  Kleine Frage: Schaffe ich es irgendwie, innerhalb einer Abfrage sowohl den Monat als auch das Jahr zu extrahieren?

                  Kleine Gegenfrage: Schaffst du es sonst, den Inhalt von mehr als nur einer Spalte zu selektieren? (Nein, SELECT * gilt hier nicht als positive Antwort.)

                  Nein, aber ich habe es jetzt mal mit

                  SELECT MONTHNAME(post_date)

                  probiert. Klappt prima. Wo muss ich denn jetzt

                  SET lc_time_names = 'de_DE'

                  hinpacken? Sowohl am Ende als auch am Anfang der Abfrage wirft mir mySQL eine Fehlermeldung aus.

                  Und wie kann ich das mit GROUP BY einbauen, sodass mir der Monatsnamen jeweils nur noch einmal angezeigt wird?

                  Ich bin für jede Antwort dankbar.

                  ha-bauer

                  1. Moin

                    SELECT MONTHNAME(post_date)

                    probiert. Klappt prima. Wo muss ich denn jetzt

                    SET lc_time_names = 'de_DE'

                    hinpacken? Sowohl am Ende als auch am Anfang der Abfrage wirft mir mySQL eine Fehlermeldung aus.

                    als extra Query muss dies vor der eigentlichen Abfrage abgefeuert werden.

                    Und wie kann ich das mit GROUP BY einbauen, sodass mir der Monatsnamen jeweils nur noch einmal angezeigt wird?

                    An die ganze Abfrage kannst du "Group By Spaltenname" anfügen.

                    Gruß Bobby

                    --
                    -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
                    ### Henry L. Mencken ###
                    -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
                    ## Viktor Frankl ###
                    ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
                    1. als extra Query muss dies vor der eigentlichen Abfrage abgefeuert werden.

                      Hat bei mir in PHPMyAdmin nicht funktioniert. Hab erst die SET- Abfrage durchgeführt (mit Erfolgsmeldung) und dann die SELECT- Abfrage, mit dem Ergebnis, dass die Einträge immer noch englisch waren.

                      An die ganze Abfrage kannst du "Group By Spaltenname" anfügen.

                      Das hat PHPMyAdmin zwar durchgehen lassen, aber es wird trotzdem nicht zusammengefasst, sondern für jeden einzelnen Eintrag der Monatsname ausgegeben.

                      Hat jemand noch einen Vorschlag?

                      Vielen Dank,

                      ha-bauer

                      P.S. Wie baue ich das ganze eigentlich in eine PHP- Abfrage ein? Mit while() habe ich es schon probiert, hat aber nicht geklappt. Hier mein Code:

                      echo "<ul>";  
                        $sql_set_time_to_dt = "SET lc_time_names = 'de_DE'";  
                        mysql_query($sql_set_time_to_dt); // Set monthnames to german  
                        $sql_archive = "SELECT MONTHNAME( post_date )  
                      FROM wp_posts  
                      WHERE post_status = 'publish'  
                      AND post_type = 'post'  
                      GROUP BY post_date";  
                        $res = mysql_query($sql_archive);  
                      while ($row = @mysql_fetch_assoc($res)) {  
                        echo "<li>{$row}</li>"; }  
                        echo "</ul>";
                      

                      Als Ergebnis erhalte ich eine ziemlich lange Liste, wo jedes Listenelement den Namen "Array" hat. Wie kann ich das richtig machen?

                      1. Hi,

                        P.S. Wie baue ich das ganze eigentlich in eine PHP- Abfrage ein?

                        Wie mache ich dies, wie mache ich jenes, und wie dann das noch ...

                        Findest du nicht, dass es langsam an der Zeit wäre, dass du erst mal dein Grundlagenwissen etwas erweiterst?
                        Suche dir ein Tutorial zum Thema, und arbeite es durch.

                        Als Ergebnis erhalte ich eine ziemlich lange Liste, wo jedes Listenelement den Namen "Array" hat.

                        mysql_fetch_assoc gibt nun mal ein Array zurück.

                        Wie kann ich das richtig machen?

                        Wenn du an den einzelnen Elementen des Arrays interessiert bist, dann greife auf sie zu. Wenn du auch das noch nicht kannst, wird's überhöchste Zeit für's Durcharbeiten eines Grundlagentutorial.

                        MfG ChrisB

                        --
                        Light travels faster than sound - that's why most people appear bright until you hear them speak.
                        1. Wenn du an den einzelnen Elementen des Arrays interessiert bist, dann greife auf sie zu.

                          Würde ich ja gerne (und ich wüsste auch, wie ich es prinzipiell machen würde), aber ich habe doch in diesem Sinne keinen Spaltennamen, den ich abfragen könnte, oder?

                          ha-bauer

                          1. Hi,

                            Wenn du an den einzelnen Elementen des Arrays interessiert bist, dann greife auf sie zu.

                            Würde ich ja gerne (und ich wüsste auch, wie ich es prinzipiell machen würde), aber ich habe doch in diesem Sinne keinen Spaltennamen, den ich abfragen könnte, oder?

                            Dann vergebe einen - Stichwort Alias.

                            MfG ChrisB

                            --
                            Light travels faster than sound - that's why most people appear bright until you hear them speak.
                            1. Hallo nochmal,

                              prima, jetzt habe ich mit AS alles so hinbekommen, wie ich es wollte.

                              Vielen Dank,

                              ha-bauer

                              1. Moin

                                prima, jetzt habe ich mit AS alles so hinbekommen, wie ich es wollte.

                                Und du hast dir vieles selbst erarbeitet anhand von Stichpunkten. Ist das nicht ein tolles Gefühl?

                                Gruß Bobby

                                --
                                -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
                                ### Henry L. Mencken ###
                                -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
                                ## Viktor Frankl ###
                                ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
                                1. Und du hast dir vieles selbst erarbeitet anhand von Stichpunkten. Ist das nicht ein tolles Gefühl?

                                  Yep.

                                  Viele Grüße,

                                  ha-bauer

                          2. Hallo,

                            Würde ich ja gerne (und ich wüsste auch, wie ich es prinzipiell machen würde), aber ich habe doch in diesem Sinne keinen Spaltennamen, den ich abfragen könnte, oder?

                            Dann vergib doch einen - »AS« ist dein Freund (siehe Doku).

                            Grüß,
                            Tobias

                      2. An die ganze Abfrage kannst du "Group By Spaltenname" anfügen.

                        Das hat jetzt geklappt:

                        SELECT MONTHNAME( post_date )  
                        FROM wp_posts  
                        WHERE post_status = 'publish'  
                        AND post_type = 'post'  
                        GROUP BY YEAR(post_date), MONTH(post_date) ORDER BY post_date  
                        DESC
                        

                        Bleibt also nur noch die Frage, wie ich das in PHP abfrage, wie ich die Abfrage deutsch hinbekomme (was wahrscheinlich klappt, wenn das eigentliche Query erst mal läuft) und wie ich an den Monatsnamen auch noch das Jahr anhängen kann.

                        Vielen Dank soweit.

                        ha-bauer

                      3. Hallo,

                        Neben dem was ChrisB schon schrieb:

                        als extra Query muss dies vor der eigentlichen Abfrage abgefeuert werden.
                        Hat bei mir in PHPMyAdmin nicht funktioniert. Hab erst die SET- Abfrage durchgeführt (mit Erfolgsmeldung) und dann die SELECT- Abfrage, mit dem Ergebnis, dass die Einträge immer noch englisch waren.

                        Der SET-Query muss in der gleichen Verbindung abgefeuert werden wie der SELECT-Query - wenn du mit PMA aber erst die Sprache änderst und dann nach dem Neuladen der Seite die Daten holst, sind das zwei verschiedene Verbindungen und MySQL hat längst wieder vergessen, dass es eigentlich die Monate auf deutsch ausgeben soll. Wenn du das Ergebnis mit PMA sehen willst, muss du die beiden Querys im gleichen Fenster mit einem Semikolon getrennt eingeben, PMA trennt die Querys dann auf und schickt sie hintereinander an die Datenbank.

                        Grüß,
                        Tobias

                        1. Der SET-Query muss in der gleichen Verbindung abgefeuert werden wie der SELECT-Query - wenn du mit PMA aber erst die Sprache änderst und dann nach dem Neuladen der Seite die Daten holst, sind das zwei verschiedene Verbindungen und MySQL hat längst wieder vergessen, dass es eigentlich die Monate auf deutsch ausgeben soll. Wenn du das Ergebnis mit PMA sehen willst, muss du die beiden Querys im gleichen Fenster mit einem Semikolon getrennt eingeben, PMA trennt die Querys dann auf und schickt sie hintereinander an die Datenbank.

                          Danke für den Tipp, jetzt hat das mit dem Eindeutschen auch geklappt.

                          ha-bauer

                  2. Hallo,

                    Wo muss ich denn jetzt
                    SET lc_time_names = 'de_DE'
                    hinpacken?

                    Das ist ein eigener Query der vor dem SELECT-Query per mysql_query() an die Datenbank geschickt werden muss.

                    Sowohl am Ende als auch am Anfang der Abfrage wirft mir mySQL eine Fehlermeldung aus.

                    Und die wäre?

                    Und wie kann ich das mit GROUP BY einbauen, sodass mir der Monatsnamen jeweils nur noch einmal angezeigt wird?

                    So wie es im Handbuch beschrieben ist.

                    Grüß,
                    Tobias

    2. Hallo Bobby,

      Du schaffst es mittels den MySQL-date und time Funktionen ein Datum formatiert auszugeben. Dazu eine kleine Function in PHP die englische in deutsche Monatsnamen tauscht und schon bekommst du diese.

      PHP brauchst du dafür nicht bemühen - das kann MySQL auch alleine: Einfach vorher den Query
       SET lc_time_names = 'de_DE'
      abfeuern und schon spuckt MySQL Wochentage und Monate auf deutsch aus, siehe Doku (die englische Doku verwenden, die deutsche ist unvollständig)

      Grüß,
      Tobias

      1. Moin

        PHP brauchst du dafür nicht bemühen - das kann MySQL auch alleine: Einfach vorher den Query
        SET lc_time_names = 'de_DE'
        abfeuern und schon spuckt MySQL Wochentage und Monate auf deutsch aus, siehe Doku (die englische Doku verwenden, die deutsche ist unvollständig)

        Danke für den Tipp. Muss ich mir merken. Kann man direkt nach Festlegung der der Kodierung (UTF-8) standardmäßig abfeuern. Oder spricht was dagegen?

        Gruß Bobby

        --
        -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
        ### Henry L. Mencken ###
        -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
        ## Viktor Frankl ###
        ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
        1. Hallo,

          SET lc_time_names = 'de_DE'
          abfeuern und schon spuckt MySQL Wochentage und Monate auf deutsch aus, siehe Doku (die englische Doku verwenden, die deutsche ist unvollständig)

          Danke für den Tipp. Muss ich mir merken.

          und die Versionsvoraussetzung beachten :-)

          Freundliche Grüße

          Vinzenz

          1. Hallo Vinzenz,

            SET lc_time_names = 'de_DE'
            [...]
            und die Versionsvoraussetzung beachten :-)

            solange man nicht noch mit einer 4.0er Version rumkrebsen muss sollte das kein Problem sein, die Doku ist an der Stelle nämlich etwas unpräzise: Wenn man sich die Doku zur Version 4.1.x (und kleiner) bzw. zur Version 5.0.x anschaut stellt man fest, dass das das mit lc_time_names auch schon ab Version 4.1.21 bzw. ab 5.0.25 funktioniert ...

            Grüß,
            Tobias

        2. Hallo Bobby,

          Danke für den Tipp. Muss ich mir merken. Kann man direkt nach Festlegung der der Kodierung (UTF-8) standardmäßig abfeuern. Oder spricht was dagegen?

          Nein, da spricht imho nichts dagegen - ich feuer den Query auch in der Datenbankklasse direkt nach dem Aufbau der Verbindung ab.

          Grüß,
          Tobias

          1. Moin

            Nein, da spricht imho nichts dagegen - ich feuer den Query auch in der Datenbankklasse direkt nach dem Aufbau der Verbindung ab.

            Das habe ich nun auch in selbige standardmäßig integriert.

            Gruß Bobby

            --
            -> Für jedes Problem gibt es eine Lösung, die einfach, sauber und falsch ist! <-
            ### Henry L. Mencken ###
            -> Nicht das Problem macht die Schwierigkeiten, sondern unsere Sichtweise! <-
            ## Viktor Frankl ###
            ie:{ br:> fl:{ va:} ls:< fo:) rl:( n4:( de:> ss:) ch:? js:( mo:} sh:) zu:)
        3. Hi!

          SET lc_time_names = 'de_DE'
          Danke für den Tipp. Muss ich mir merken. Kann man direkt nach Festlegung der der Kodierung (UTF-8) standardmäßig abfeuern. Oder spricht was dagegen?

          Dagegen kann sprechen, dass du ihn nur in x% deiner Abfragen brauchst, dafür aber beim Rest jedes Mal einen unnötigen Roundtrip vollführst.

          Alternative Vorschläge:
          Als Administrator und Alleinnutzer kann man den Wert unter init_connect setzen, was automatisch bei jedem Connect und serverseitig und damit ohne Roundtrip passiert.

          Als Anwender kann man zumindest mit mysqli_multi_query() einen Roundtrip sparen, wenn man SET NAMES und SET lc_time_names in einem Abwasch erledigt. (Normalerweise sollte man mysql(i)_set_charset() verwenden, aber der Unterschied zu SET NAMES spielt bei Latin1 und UTF-8 keine Rolle.)

          Lo!

          1. Moin!

            Als Anwender kann man zumindest mit mysqli_multi_query() einen Roundtrip sparen, wenn man SET NAMES und SET lc_time_names in einem Abwasch erledigt. (Normalerweise sollte man mysql(i)_set_charset() verwenden, aber der Unterschied zu SET NAMES spielt bei Latin1 und UTF-8 keine Rolle.)

            mysqli_multi_query hat so seine Besonderheiten in der Nutzung. Das kann man nicht analog zu mysqli_query benutzen, ohne die Ergebnisse der einzelnen Abfragen abzuholen.

            - Sven Rautenberg

            1. Hi,

              Als Anwender kann man zumindest mit mysqli_multi_query() einen Roundtrip sparen, wenn man SET NAMES und SET lc_time_names in einem Abwasch erledigt. (Normalerweise sollte man mysql(i)_set_charset() verwenden, aber der Unterschied zu SET NAMES spielt bei Latin1 und UTF-8 keine Rolle.)

              mysqli_multi_query hat so seine Besonderheiten in der Nutzung. Das kann man nicht analog zu mysqli_query benutzen, ohne die Ergebnisse der einzelnen Abfragen abzuholen.

              Dann vielleicht doch lieber gleich Zeichenkodierung und Locale schon beim herstellen der Verbindung über mysqli::options angeben.
              (Das nimnt doch mehrere Statements durch Semikolon getrennt, oder? Hab's ehrlich gesagt noch nicht mit mehr als einer Anweisung probiert.)

              MfG ChrisB

              --
              Light travels faster than sound - that's why most people appear bright until you hear them speak.
              1. Hi!

                mysqli_multi_query hat so seine Besonderheiten in der Nutzung. Das kann man nicht analog zu mysqli_query benutzen, ohne die Ergebnisse der einzelnen Abfragen abzuholen.

                Guter Einwand. Danke.
                Das ergibt einen "Commands out of sync; you can't run this command now"-Fehler bei den nachfolgenden Querys, wenn man die Ergebnisse nicht abholt.

                Dann vielleicht doch lieber gleich Zeichenkodierung und Locale schon beim herstellen der Verbindung über mysqli::options angeben.

                Du meinst sicher über die Option MYSQLI_INIT_COMMAND.

                (Das nimnt doch mehrere Statements durch Semikolon getrennt, oder? Hab's ehrlich gesagt noch nicht mit mehr als einer Anweisung probiert.)

                Ich habe es probiert und es wird abgewiesen. Der Teil nach dem Semikolon wird als syntaktisch falsch beanstandet. In der Konfigurationsdatei MySQLs hingegen kann man im init-connect mehrere Statements angeben.

                Lo!