Ich versuche, Datensätze nach Woche zu gruppieren und das aggregierte Datum als ersten Tag der Woche zu speichern. Die Standardtechnik, die ich zum Abrunden von Daten verwende, scheint jedoch mit Wochen nicht richtig zu funktionieren (obwohl dies für Tage, Monate, Jahre, Quartale und andere Zeiträume gilt, auf die ich sie angewendet habe).
Hier ist die SQL:
select "start_of_week" = dateadd(week, datediff(week, 0, getdate()), 0);
Dies kehrt zurück 2011-08-22 00:00:00.000
, was ein Montag ist, kein Sonntag. Wenn Sie @@datefirst
Returns auswählen 7
, ist dies der Code für Sonntag, damit der Server meines Wissens korrekt eingerichtet ist.
Ich kann dies leicht genug umgehen, indem ich den obigen Code in ändere:
select "start_of_week" = dateadd(week, datediff(week, 0, getdate()), -1);
Aber die Tatsache, dass ich eine solche Ausnahme machen muss, macht mich ein wenig unruhig. Ich entschuldige mich auch, wenn dies eine doppelte Frage ist. Ich habe einige verwandte Fragen gefunden, aber keine, die diesen Aspekt speziell angesprochen haben.
quelle
(@@DATEFIRST + DATEPART(DW, @SomeDate)) % 7
bleibt konstant, unabhängig von der@@datefirst
Einstellung, denke ich. Mit Montag = 2.Antworten:
Um zu beantworten, warum Sie einen Montag und keinen Sonntag bekommen:
Sie fügen dem Datum 0 eine Anzahl von Wochen hinzu. Was ist das Datum 0? 1900-01-01. Was war der Tag am 1900-01-01? Montag. In Ihrem Code sagen Sie also, wie viele Wochen sind seit Montag, dem 1. Januar 1900 vergangen? Nennen wir das [n]. Ok, fügen Sie jetzt [n] Wochen zum Montag, dem 1. Januar 1900, hinzu. Sie sollten sich nicht wundern, dass dies ein Montag wird.
DATEADD
hat keine Ahnung, dass Sie Wochen hinzufügen möchten, aber nur bis Sie zu einem Sonntag kommen, es werden nur 7 Tage und dann 7 weitere Tage hinzugefügt, ... genau wieDATEDIFF
nur Grenzen erkannt werden, die überschritten wurden. Zum Beispiel geben beide 1 zurück, obwohl sich einige Leute darüber beschweren, dass eine vernünftige Logik eingebaut sein sollte, um auf- oder abzurunden:Um zu beantworten, wie man einen Sonntag bekommt:
Wenn Sie einen Sonntag wünschen, wählen Sie ein Basisdatum, das kein Montag, sondern ein Sonntag ist. Beispielsweise:
Dies wird nicht unterbrochen, wenn Sie Ihre
DATEFIRST
Einstellung ändern (oder Ihr Code für einen Benutzer mit einer anderen Einstellung ausgeführt wird) - vorausgesetzt, Sie möchten unabhängig von der aktuellen Einstellung weiterhin einen Sonntag. Wenn Sie möchten, dass diese beiden Antworten funktionieren, sollten Sie eine Funktion verwenden, die von derDATEFIRST
Einstellung abhängt , zWenn Sie also Ihre
DATEFIRST
Einstellung auf Montag, Dienstag ändern, ändert sich das Verhalten. Je nachdem, welches Verhalten Sie möchten, können Sie eine der folgenden Funktionen verwenden:...oder...
Jetzt haben Sie viele Alternativen, aber welche ist die beste? Ich wäre überrascht, wenn es größere Unterschiede geben würde, aber ich habe alle bisher gegebenen Antworten gesammelt und zwei Testreihen durchlaufen - eine billige und eine teure. Ich habe Client-Statistiken gemessen, weil ich nicht sehe, dass E / A oder Speicher hier eine Rolle bei der Leistung spielen (obwohl diese je nach Verwendung der Funktion ins Spiel kommen können). In meinen Tests sind die Ergebnisse:
Zuweisungsabfrage "Günstig":
"Teure" Zuweisungsabfrage:
Auf Wunsch kann ich die Details meiner Tests weitergeben - hier anhalten, da dies bereits ziemlich langwierig wird. Ich war ein bisschen überrascht zu sehen, dass Curt's angesichts der Anzahl der Berechnungen und des Inline-Codes am schnellsten als der schnellste herauskam. Vielleicht führe ich gründlichere Tests durch und blogge darüber ... wenn ihr keine Einwände dagegen habt, dass ich eure Funktionen woanders veröffentliche.
quelle
Für diese, die bekommen müssen:
Montag = 1 und Sonntag = 7:
Sonntag = 1 und Samstag = 7:
Oben gab es ein ähnliches Beispiel, aber dank doppeltem "% 7" wäre es viel langsamer.
quelle
select (datediff(dd,5,cal.D_DATE)%7 + 1)
undselect (datediff(dd,6,cal.D_DATE)%7 + 1)
Für diejenigen, die die Antwort bei der Arbeit benötigen und das Erstellen von Funktionen von Ihrem DBA verboten ist, funktioniert die folgende Lösung:
Dies gibt den Beginn dieser Woche. Hier gehe ich davon aus, dass Sonntage der Beginn von Wochen sind. Wenn Sie denken, dass Montag der Anfang ist, sollten Sie verwenden:
quelle
Das funktioniert wunderbar für mich:
quelle
Googelte dieses Skript:
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=47307
quelle
Vielleicht brauchst du das:
Oder
Funktion
quelle
DATEPART(DW
ist abhängig von@@datefirst
DATE
dann müssen Sie keine suboptimalen Konvertierungen hinVARCHAR
und zurück durchführen, um eine versehentlicheTime
Werte benötigt .quelle
Für die Basis (der Sonntag der aktuellen Woche)
Wenn letzte Woche:
Intern haben wir eine Funktion erstellt, die dies tut. Wenn Sie jedoch schnell und schmutzig arbeiten müssen, ist dies der Fall.
quelle
Da das julianische Datum 0 ein Montag ist, addieren Sie einfach die Anzahl der Wochen zum Sonntag, der der Tag vor -1 ist. Wählen Sie dateadd (wk, dateiff (wk, 0, getdate ()), - 1).
quelle
Das ist meine Logik. Stellen Sie den ersten der Woche auf Montag ein und berechnen Sie dann den Wochentag, an dem ein bestimmter Tag ist. Berechnen Sie dann mit DateAdd und Case I, wie das Datum am vorherigen Montag dieser Woche gewesen wäre.
quelle
Ich habe keine Probleme mit den hier gegebenen Antworten, aber ich denke, meine ist viel einfacher zu implementieren und zu verstehen. Ich habe keine Leistungstests durchgeführt, aber es sollte vernachlässigbar sein.
Daher habe ich meine Antwort aus der Tatsache abgeleitet, dass Datumsangaben als Ganzzahlen in SQL Server gespeichert sind (ich spreche nur von der Datumskomponente). Wenn Sie mir nicht glauben, versuchen Sie es mit SELECT CONVERT (INT, GETDATE ()) und umgekehrt.
Wenn Sie dies wissen, können Sie einige coole mathematische Gleichungen machen. Vielleicht können Sie sich eine bessere einfallen lassen, aber hier ist meine.
quelle
@@DATEFIRST
ist auch 7, aber wenn Ihr@testDate
der Beginn der Woche ist, gibt dies ein Datum zurück, das der Tag zuvor ist.Ich hatte ein ähnliches Problem. Angesichts eines Datums wollte ich das Datum des Montags dieser Woche erhalten.
Ich habe die folgende Logik verwendet: Finden Sie die Tagesnummer in der Woche im Bereich von 0-6 und subtrahieren Sie diese vom Ursprungsdatum.
Ich habe verwendet: DATEADD (Tag, - (DATEPART (Wochentag,) + 5)% 7,)
Da DATEPRRT (Wochentag) 1 = Sonntag ... 7 = Samstag zurückgibt, gibt DATEPART (Wochentag) + 5)% 7 0 = Montag ... 6 = Sonntag zurück.
Wenn Sie diese Anzahl von Tagen vom ursprünglichen Datum abziehen, erhalten Sie den vorherigen Montag. Die gleiche Technik kann für jeden Starttag der Woche angewendet werden.
quelle
Ich fand das einfach und nützlich. Funktioniert auch, wenn der erste Wochentag Sonntag oder Montag ist.
DECLARE @BaseDate AS Date
SET @BaseDate = GETDATE ()
DECLARE @FisrtDOW AS Date
SELECT @FirstDOW = DATEADD (d, DATEPART (WOCHENTAG, @ BaseDate) * -1 + 1, @BaseDate)
quelle
Vielleicht bin ich hier zu stark vereinfacht, und das mag der Fall sein, aber das scheint für mich zu funktionieren. Ich habe noch keine Probleme damit gehabt ...
quelle
SET DATEFIRST
.DATEFIRST
(seit dreieinhalb Jahren) und tut es immer noch nicht. Und Sie sollten auch regionale Formate wie vermeidenm/d/y
, selbst in Szenarien, in denen m und d gleich sind.