Sam: SQL, Datumsfunktionen

Hallo!

Ich möchte per SQL das Beginndatum des nächsten Schulhalbjahrs ermitteln - das ist immer der 1.2. und der 1.8.
Also aus heutiger Sicht wäre das gesuchte Datum der 1.2.2008.

Ich habe unter [URL:http://www.insidesql.de/content/view/261/3/] folgende Infos gefunden, die in diese Richtung gehen.
Leider habe ich das Prinzip aber doch zu wenig verstanden, um daraus die Lösung zu meiner Aufgabenstellung abzuleiten.

Kann mir jemand helfen?
LG, Sam

<quote>
Die Methode, die die String Konvertierung verwendet kann nur verwendet werden, um den Zeitanteil aus einem Datum zu entfernen. Die DATEADD(DATEDIFF Methode hingegen kann sehr leicht verändert werden, um z.B. den Monats-, Quartals- oder Jahresanfang zu ermitteln. SELECT DATEADD(month, DATEDIFF(month, '20000101', CURRENT_TIMESTAMP), '20000101'). Oder um nur die Minuten und Sekunden oder nur die Sekunden zu entfernen. SELECT DATEADD(hour, DATEDIFF(hour, '20000101', CURRENT_TIMESTAMP), '20000101') (Achtung - wenn man mit Minuten arbeitet, kann die DATEDIFF Funktion einen Überlauf des Integer Bereiches verursachen - die Datumskonstante muß dann in diesen Fällen entsprechend angepasst werden.  Weitere Einsatzgebiete sind ebenfalls denkbar.  Wie erhält man den letzten Tag des Vormonats? Und wie den letzten Tag des aktuellen Monats?
SELECT DATEADD(month, DATEDIFF(month, '20000101', CURRENT_TIMESTAMP), '19991231')
SELECT DATEADD(month, DATEDIFF(month, '20000101', CURRENT_TIMESTAMP), '20000131')

Wie erhält man das morgige Datum (ohne Zeit)?
SELECT DATEADD(day, DATEDIFF(day, '20000101', CURRENT_TIMESTAMP), '20000102')

Wie rundet man auf die nächste volle Stunde, auf den nächsten vollen Tag?
SELECT DATEADD(hour, DATEDIFF(hour, '20000101', DATEADD(minute, 30, CURRENT_TIMESTAMP)), '20000101')
SELECT DATEADD(day, DATEDIFF(day, '20000101', DATEADD(hour, 12, CURRENT_TIMESTAMP)), '20000101')

Wie erhält man den letzten Freitag, ohne eine Kalendartabelle zu verwenden und ohne von der aktuellen DATEFIRST Einstellung abhängig zu sein?
SELECT DATEADD(day, (DATEDIFF (day, '20000107', CURRENT_TIMESTAMP) / 7) * 7, '20000107')

oder
SELECT DATEADD(day, (DATEDIFF (day, '20000108', CURRENT_TIMESTAMP) / 7) * 7, '20000107')

Das erstere gibt den aktuellen Tag zurück, wenn man es an einem Freitag laufen läßt, das letztere gibt den letzten Freitag davor zurück.

Hat man erst einmal das generelle Prinzip verstanden, ist es einfach, neue Variationen zu finden, die in bestimmten Situationen nützlich sein können.
</quote>

  1. yo,

    verräst du uns auch, welches dbms du verwendest ? ich tippe mal auf mysql, aber man weiss ja nie.....

    Ilja

    1. verräst du uns auch, welches dbms du verwendest ? ich tippe mal auf mysql, aber man weiss ja nie.....

      ah, sorry, vergessen  .... MS SQL Server 2005

      1. yo,

        select
         CASE
          WHEN '01.02.' + CAST(YEAR(GETDATE()) AS CHAR) < GETDATE()
          THEN '01.08.' + CAST(YEAR(GETDATE()) AS CHAR)
          ELSE '01.02.' + CAST(YEAR(GETDATE()) AS CHAR)
         END

        Ilja

        1. upps, da habe ich noch vergessen, an einer stelle noch eine 1 zum Jahr zu addieren, das solltest du aber auch alleine hinbekommen, ansonsten noch mal nachfragen.

          PS: wo ist de hier nur eine edit-funktion.....

          Ilja

          1. upps, da habe ich noch vergessen, an einer stelle noch eine 1 zum Jahr zu addieren, das solltest du aber auch alleine hinbekommen, ansonsten noch mal nachfragen.

            Ja, vielen Dank, komme klar, hat mir sehr geholfen!

            1. yo,

              neben der 1 war auch noch ein Logik-fehler bei mir oder sind eventuell noch mehrere versteckt. hier mal die letzte, die ich schnell ausprobiert habe...

              select
               CASE
                WHEN GETDATE() < '01.02.' + CAST(YEAR(GETDATE()) AS CHAR)
                THEN '01.02.' + CAST(YEAR(GETDATE()) AS CHAR)
                WHEN GETDATE() BETWEEN '01.02.' + CAST(YEAR(GETDATE()) AS CHAR) AND '01.08.' + CAST(YEAR(GETDATE()) AS CHAR)
                THEN '01.08.' + CAST(YEAR(GETDATE()) AS CHAR)
                ELSE '01.02.' + CAST(YEAR(GETDATE()) + 1 AS CHAR)
               END

              Ilja

              1. yo,

                neben der 1 war auch noch ein Logik-fehler bei mir oder sind eventuell noch mehrere versteckt. hier mal die letzte, die ich schnell ausprobiert habe...

                genau ;-)
                Meine Version ist

                SELECT
                CAST(
                CASE
                WHEN CAST(MONTH(GETDATE()) AS INT) >= 2 AND CAST(MONTH(GETDATE()) AS INT) < 8
                THEN '01.08.' + CAST(YEAR(GETDATE()) AS CHAR)
                ELSE
                CASE
                WHEN CAST(MONTH(GETDATE()) AS INT) = 1
                THEN '01.02.' + CAST(YEAR(GETDATE()) AS CHAR)
                ELSE '01.02.' + CAST(YEAR(GETDATE()) + 1 AS CHAR)
                END
                END
                AS DATETIME) AS halbjahr

                Ok, etwas umständlich ... aber fnktioniert auch  :-)
                Merci!
                Sam

                select
                CASE
                  WHEN GETDATE() < '01.02.' + CAST(YEAR(GETDATE()) AS CHAR)
                  THEN '01.02.' + CAST(YEAR(GETDATE()) AS CHAR)
                  WHEN GETDATE() BETWEEN '01.02.' + CAST(YEAR(GETDATE()) AS CHAR) AND '01.08.' + CAST(YEAR(GETDATE()) AS CHAR)
                  THEN '01.08.' + CAST(YEAR(GETDATE()) AS CHAR)
                  ELSE '01.02.' + CAST(YEAR(GETDATE()) + 1 AS CHAR)
                END

                Ilja

              2. Hallo Ilja,

                neben der 1 war auch noch ein Logik-fehler bei mir oder sind eventuell noch mehrere versteckt. hier mal die letzte, die ich schnell ausprobiert habe...

                select
                CASE
                  WHEN GETDATE() < '01.02.' + CAST(YEAR(GETDATE()) AS CHAR)
                  THEN '01.02.' + CAST(YEAR(GETDATE()) AS CHAR)
                  WHEN GETDATE() BETWEEN '01.02.' + CAST(YEAR(GETDATE()) AS CHAR) AND '01.08.' + CAST(YEAR(GETDATE()) AS CHAR)
                  THEN '01.08.' + CAST(YEAR(GETDATE()) AS CHAR)
                  ELSE '01.02.' + CAST(YEAR(GETDATE()) + 1 AS CHAR)
                END

                meine Version nimmt explizites Umwandeln vor, um sich länderspezifische
                Probleme zu ersparen. Sie liefert einen DATETIME-Wert zurück.

                Weiterhin nutze ich die Eigenschaft (Zitat aus der Doku):

                Der result_expression-Ausdruck des ersten Boolean_expression-Ausdrucks, der zu TRUE ausgewertet wird, wird zurückgegeben.

                und verzichte daher auf BETWEEN, wobei BETWEEN schöner die Teilung des Jahres
                in drei Abschnitte widerspiegelt.

                Ich gehe davon aus, dass am 01.02. der 01.02. auch noch als Einschulung erlaubt ist.

                  
                SELECT  
                    Einschulung = CASE  
                    WHEN SUBSTRING(CONVERT(VARCHAR(8), GETDATE(), 112),5, 4) < '0202'  
                     THEN CONVERT(DATETIME, CAST(YEAR(GETDATE()) AS VARCHAR(4)) + '0201', 112)  
                    WHEN SUBSTRING(CONVERT(VARCHAR(8), GETDATE(), 112),5, 4) < '0802'  
                     THEN CONVERT(DATETIME, CAST(YEAR(GETDATE()) AS VARCHAR(4)) + '0801', 112)  
                    ELSE  
                        CONVERT(DATETIME, CAST(YEAR(GETDATE()) + 1 AS VARCHAR(4)) + '0201', 112)  
                    END  
                
                

                Freundliche Grüße

                Vinzenz

                1. yo Vinz,

                  ja, meine abfrage hat mir selbst nicht gefallen, war ein wenig schnell dahin geschrieben, ohne zuviel gehirn-schmalz zu investieren. das geht in aller regel immer nicht gut aus. ;-)

                  um ein paar denkanstösse zu geben, hat es ja zum glück gereicht.

                  Der result_expression-Ausdruck des ersten Boolean_expression-Ausdrucks, der zu TRUE ausgewertet wird, wird zurückgegeben.

                  hmm, da bin ich skeptisch, wenn man nun schon eine so ordentliche typen-umwandlung macht(was sehr sinnvoll ist), dann sollte man auch explizit alle fälle durchgehen und den else fall eventuell mit NULL abfangen. meine erfahrung ist, dass es weniger fehleranfällig ist, wenn man alle fälle durchgeht und den else fall als "kein ergebnis" benutzt und vor allem die oben genanten "funktion" nicht ausnutzt. macht neben der kleineren fehleranfälligkeit auch besser lesbar.

                  Gruß
                  Ilja