Norbert: Rest eines Monates mit SQL ermitteln

Hallo,

eigentlich steht schon alles im Subjekt.
Um die Differenz zweier gegebener Termine zu berechnen, braucht man auch den Monatsrest des aelteren Datums. Die Differenz ueber den Timestamp zu berechnen schlaegt fehl, da auch viele Zeitpunkte weit vor 1970 liegen.

z.B. MONTH_REST('1983-02-15') ergaebe 13 Tage
oder MONTH_REST('1980-02-21') ergaebe 8 Tage

Da ich keine SQL-Funktion MONTH_REST() kenne, brauche ich einen Workaround.
Kann mir da bitte jemand helfen ...

Gruss und Dank
Norbert

  1. Hello Norbert,

    die Datenbankprogramme haben eigentlich alle unterschiedliche Wertebereiche für ihren Datumstyp. Es wäre daher sehr hilfreich, wenn Du die Datenbankmaschine bezeichnen würdest.

    Der Unix-Timestamp wird zwar für die meisten Datumsfunktionen in vielen Scriptsprachen (z.B. PHP) verwendet, nicht aber unbedingt in den Datenbanksystemen...

    Harzliche Grüße vom Berg
    http://www.annerschbarrich.de

    Tom

    --
    Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
    Nur selber lernen macht schlau

    1. Hallo Tom,

      oops, sind die Vorgaben geaendert worden?
      IMHO steht irgendwo, dass wenn nicht anders angegeben, von MySQL 3.X ausgegangen wird.
      Okay, meistenteils ist mittlerweile sicher ein 4-er oder 5-er MySQL am Start, aber MySQL isses immer noch.

      Gruss und Dank
      Norbert

      1. Hello,

        oops, sind die Vorgaben geaendert worden?

        Welche Vorgaben?

        IMHO steht irgendwo, dass wenn nicht anders angegeben, von MySQL 3.X ausgegangen wird.

        Wenn sogar ich das inzwischen ad acta gelegt habe, wird wohl kaum jemand anderes noch von MySQL 3.x ausgehen hier.

        Okay, meistenteils ist mittlerweile sicher ein 4-er oder 5-er MySQL am Start, aber MySQL isses immer noch.

        Datum im Format 'YYYY-MM-DD'. Wertebereich von 01.01.1000 bis 31.12.9999.
          Ab MySQL 4.1 gilt das auch für den Spaltentyp TIMESTAMP

        Allerdings weiß ich nicht, wie genau die Funktionen tatsächlich sind.
        Interessant wäre mal, die Anzahl der Tage zwischen dem 04. und dem 15. Oktober 1582 abzufragen.
        Damit kann man jeden Datenbankprogrammierer, der geschichtliche Ereignisse verarbeiten muss, zur Weißglut bringen ;-)

        Ans Herz legen möchte ich Dir noch das Manual:
        http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html

        Die Aufgabe, wieviele Resttage der Monat noch hat, lässt sich mit Hilfe der Funktion
        http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_dayofmonth feststellen

        Pseudo-Code:

        Resttage = 31 - dayofmonth(aktuelles_Datum + 31)

        Gilt zumindest für den Gregorianischen Kalender ;-))

        Harzliche Grüße vom Berg
        http://www.annerschbarrich.de

        Tom

        --
        Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
        Nur selber lernen macht schlau

        1. Hai Tom,

          Ans Herz legen möchte ich Dir noch das Manual:
          http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html

          Witzbold ... ;-)

          Die Aufgabe, wieviele Resttage der Monat noch hat, lässt sich mit Hilfe der Funktion
          http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#function_dayofmonth

          feststellen

          Pseudo-Code:
             Resttage = 31 - dayofmonth(aktuelles_Datum + 31)
          Gilt zumindest für den Gregorianischen Kalender ;-))

          hmm,
          da habe ich so meine Zweifel, schau mal hier:

          SELECT geb,  DAYOFMONTH(geb), (31 - DAYOFMONTH(geb + 31)) FROM persons;
          erzeugt:
          +------------+-----+-------+
          | 1960-02-28 |  28 |  NULL |
          | 1965-03-06 |   6 |  NULL |
          | 1969-03-06 |   6 |  NULL |
          | 1972-01-20 |  20 |  NULL |
          | 1959-10-11 |  11 |  NULL |
          ............................
          ............................
          ............................
          | 1966-10-11 |  11 |  NULL |
          | 1960-02-15 |  15 |  NULL |
          | 1964-05-18 |  18 |  NULL |
          | 1966-09-28 |  28 |  NULL |
          | 1947-01-21 |  21 |  NULL |
          +------------+-----+-------+
          82 rows in set, 82 warnings (0.00 sec)

          Da faellt mir noch eine Frage ein:
          Wo findet man eigentlich die 82 Warnings?

          Gruss und Dank
          Norbert

          1. Hello,

            da habe ich so meine Zweifel, schau mal hier:

            SELECT geb,  DAYOFMONTH(geb), (31 - DAYOFMONTH(geb + 31)) FROM persons;
            erzeugt:
            +------------+-----+-------+
            | 1960-02-28 |  28 |  NULL |
            | 1965-03-06 |   6 |  NULL |
            | 1969-03-06 |   6 |  NULL |
            | 1972-01-20 |  20 |  NULL |
            | 1959-10-11 |  11 |  NULL |
            ............................
            ............................
            ............................
            | 1966-10-11 |  11 |  NULL |
            | 1960-02-15 |  15 |  NULL |
            | 1964-05-18 |  18 |  NULL |
            | 1966-09-28 |  28 |  NULL |
            | 1947-01-21 |  21 |  NULL |
            +------------+-----+-------+
            82 rows in set, 82 warnings (0.00 sec)

            Was soll denn das werden?

            DAYOFMONTH(geb + 31)

            geb ist doch sicher vom Typ DATETIME, oder?
            Wie addiert man zu einen Datum vom Typ DATETIME 31 Tage?

            siehe "date_add"

            außerdem gibt es auch noch andere Lösungsansätze

            siehe "last_day"

            Darum hat Dir der "Witzbold" die Datumsfunktionen ans Herz gelegt und nicht, dass Du arrogant darüber hinweggehst...

            Harzliche Grüße vom Berg
            http://www.annerschbarrich.de

            Tom

            --
            Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
            Nur selber lernen macht schlau

            1. Hallo,

              Was soll denn das werden?
                  DAYOFMONTH(geb + 31)

              hmm,
              ein unhaltbarer Versuch den Gespraechspartner ernst zu nehmen - tut mir leid - sorry ...

              geb ist doch sicher vom Typ DATETIME, oder?

              nee,
              Deine Glaskugel sollte auch mal zur Durchsicht ...

              außerdem gibt es auch noch andere Lösungsansätze
                 siehe "last_day"

              hmm,
              existiert in dem Handbuch zu 4.1 nicht, aber es geht!
              Tut mir leid, ich weiss nicht, wann der Provider MySQL updatet.

              Gruss und Dank
              Norbert

              1. Hello Norbert,

                Was soll denn das werden?
                    DAYOFMONTH(geb + 31)
                hmm,
                ein unhaltbarer Versuch den Gespraechspartner ernst zu nehmen - tut mir leid - sorry ...

                geb ist doch sicher vom Typ DATETIME, oder?
                nee,
                Deine Glaskugel sollte auch mal zur Durchsicht ...

                Du solltest dringend zwei Dinge tun:

                • die Charta des Forums durchlesen http://forum.de.selfhtml.org/hilfe/charta.htm

                • Dir darüber klar werden, dass es nirgendwo preiswertere Hilfe gibt, als hier.
                    Wenn Du Dir diese Hilfe aber selber versaust dadurch, dass Du selbst auf Rückfrage nicht
                    die erforderlichen Auskünfte gibst, dann hilft Dir auch meine "Glaskugel" nicht.
                    Und sei versichert: Ich gehöre nicht zu den "Hardcore-Antwortern..."

                Harzliche Grüße vom Berg
                http://www.annerschbarrich.de

                Tom

                --
                Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
                Nur selber lernen macht schlau

                1. Hallo Tom,

                  nur zu Deiner Information, dieses Forum ist eines, wo man als Fragender mitunter grundlos beschimpft und beleidigt wird. Die Charta gilt hier offensichtlich nur fuer Fragesteller. Einige der Hardcore-Antworter koennen froh sein, dass deutsche Gerichte auf Beleidigungsklagen noch sehr schlaff reagieren.

                  Wenn es Dich aergert hier kostenlos zu helfen, dann macht doch ein Login mit Chash. Loesungen haben wir auch gefunden, als es noch keine Internet-Foren gab. Hat zwar laenger gedauert, aber irgendwas ist ja immer ... ;-)

                  Schoenen Sonntag noch
                  Gruss Norbert

                  1. [... Vorurteile ...]

                    Du solltest Stonies Wiedereröffnungsposting lesen. Genau das, was du hier anbringst, hat zum versauten Forumsklima und zu einem kleinen Teil auch zur Forumspause geführt. Ich persönlich finde, dass nach der Wiedereröffnung hier ein wesentlich entspannteres Klima herrscht, und das sollte möglichst lange so bleiben. Und damit wäre ich beim Thema: Was für die Stammposter fürderhin gilt, gilt auch für gelegentliche Besucher wie dich. Hier wird niemand mehr dumm angemacht, das Forum soll vom respektvollen Umgang miteinander geprägt sein. Wem das nicht passt, den wollen wir hier nicht mehr sehen.

                    Solche Kommentare wie deiner sind nicht hilfreich, sondern kontraproduktiv. Jeder sollte diesem Forum und seinen Benutzern eine Chance geben, trotz bestehender Vorurteile. Es wäre schön, wenn auch du dies tun würdest.

                    Siechfred

                    1. Hallo Siechfred,

                      eigentlich suche ich nur Loesungen, die ich, warum auch immer, selbst nicht gefunden habe, obwohl ich die meisten Manuale, Handbuecher, Google, WikiPedia und die eine oder andere nette Kollegin schon bemueht habe.
                      D.h. ich versuche weitestgehend OHNE dieses oder andere Foren auszukommen, weil man oft nur bloed angemacht wird. Das beginnt schon bei der Anrede und geht dann munter fort. Meistens versuche ich das zu ignorieren, weil mir Diskussionen, so wie diese hier, auch nicht weiterhelfen, aber manchmal muss ich meinen Frust auch einfach demjenigen zeigen, der ihn verursacht hat. Okay, in Foren kann das dann jeder lesen, und mit Googles Hilfe auch noch in 10 Jahren, aber das sollten sich die Leute vorher ueberlegen, bevor sie versuchen harmlose Rentner zu aergern.

                      Mit friedfertigen Gruessen
                      Norbert

              2. Hallo,

                sorry, bei dem Kindergartenkram (man kommt sich hier manchmal wie auf einer Versammlung der RLP-Linken vor) ging die Loesung total unter.

                Also, das Query liefert den Abstand(Alter) zu einem gegebenen Datum in Jahren, Monaten und Tagen, wobei der "Rest des Monates" mitunter auch benoetigt wird:

                SELECT geb,
                 IF ((DAYOFYEAR(CURDATE()) > DAYOFYEAR(geb)),
                    (YEAR(CURDATE()) - YEAR(geb)),
                    (YEAR(CURDATE()) - YEAR(geb) - 1)) AS Jahre,
                 IF ((DAYOFYEAR(CURDATE()) > DAYOFYEAR(geb)),
                    (MONTH(CURDATE()) - MONTH(geb)),
                    (12 - (MONTH(geb) - MONTH(CURDATE())))) AS Monate,
                 IF ((DAY(CURDATE()) > DAY(geb)),
                    (DAY(CURDATE()) - DAY(geb)),
                    (DAY(LAST_DAY(geb)) - DAY(geb)) + DAY(CURDATE())) AS Tage
                 FROM test.persons ORDER BY DAY(geb) ASC;

                Nur, falls das mal jemand braucht ... ;-)

                Gruss und Dank
                Norbert

        2. echo $begrüßung;

          Datum im Format 'YYYY-MM-DD'. Wertebereich von 01.01.1000 bis 31.12.9999.
            Ab MySQL 4.1 gilt das auch für den Spaltentyp TIMESTAMP

          Entschuldige bitte, wenn ich zweifle, aber kannst du mir bitte eine Quelle nennen, die solch einen Wertebereich für TIMESTAMP angibt? Ich finde nur die Angabe im Kapitel Data Type Storage Requirements: »TIMESTAMP: A four-byte integer representing seconds UTC since the epoch ('1970-01-01 00:00:00' UTC)«
          Oder bezog sich die zweite Zeile nur auf den ersten Satz?

          echo "$verabschiedung $name";

          1. Hello,

            echo $begrüßung;

            Datum im Format 'YYYY-MM-DD'. Wertebereich von 01.01.1000 bis 31.12.9999.
              Ab MySQL 4.1 gilt das auch für den Spaltentyp TIMESTAMP

            Entschuldige bitte, wenn ich zweifle, aber kannst du mir bitte eine Quelle nennen, die solch einen Wertebereich für TIMESTAMP angibt?

            Sorry, das bezog sich nur auf die Darstellung. Hab ich mich verguckt.

            http://www.schmager.de/mysql.php

            Daten kleiner als 01.01.1970 werden bei Timestamp nicht angenommen.

            Harzliche Grüße vom Berg
            http://www.annerschbarrich.de

            Tom

            --
            Fortschritt entsteht nur durch die Auseinandersetzung der Kreativen
            Nur selber lernen macht schlau

      2. Hallo Norbert,

        oops, sind die Vorgaben geaendert worden?
        IMHO steht irgendwo, dass wenn nicht anders angegeben, von MySQL 3.X ausgegangen wird.

        Nicht hier, diese Vorgabe steht bei spotlight.de.

        Grüße aus Nürnberg
        Tobias

  2. Hi,

    eigentlich steht schon alles im Subjekt.
    Um die Differenz zweier gegebener Termine zu berechnen, braucht man auch den Monatsrest des aelteren Datums. Die Differenz ueber den Timestamp zu berechnen schlaegt fehl, da auch viele Zeitpunkte weit vor 1970 liegen.

    Verstehe ich nicht. Warum brauchst du dafür die Tage bis zum Ende des Monats?
    In mySql 4.1 gibt es beispielsweise die Funktion DATEDIFF mit der man die Differenz zwischen 2 Datumsangaben berechnen kann.

    z.B. MONTH_REST('1983-02-15') ergaebe 13 Tage
    oder MONTH_REST('1980-02-21') ergaebe 8 Tage

    Da ich keine SQL-Funktion MONTH_REST() kenne, brauche ich einen Workaround.
    Kann mir da bitte jemand helfen ...

    Du könntest ja die Tage bis zum ersten des folgemonats berechnen.

    mfG,
    steckl

  3. Hallo Norbert,

    z.B. MONTH_REST('1983-02-15') ergaebe 13 Tage
    oder MONTH_REST('1980-02-21') ergaebe 8 Tage

    Du brauchst die Funktion LAST_DAY() (verfügbar ab MySQL 4.1.1):
     SELECT DAY(LAST_DAY('1980-02-21')) - DAY('1980-02-21')
    -> 8

    Grüße aus Nürnberg
    Tobias