SQL, Datumsfunktionen
Sam
- datenbank
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>
yo,
verräst du uns auch, welches dbms du verwendest ? ich tippe mal auf mysql, aber man weiss ja nie.....
Ilja
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
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
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
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!
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
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)
ENDIlja
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
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