Benutzer mit den meisten Antworten
GETDATE - Vorletzte Woche

Frage
-
Hallo zusammen,
Ich möchte in einer Abfrage alle Datensätze der vorletzten Woche ausgeben, bzw. die Datensätze der vorletzten 7 Tage.
Das würde heissen:("Heute" - 7 Tage ) ("ab hier" - die folgenden 7 Tage)
Momentan geschieht dier per OFFSET 'Anzahl der Datensätze' FETCH NEXT 'Anzahl der Datensätze der letzten 7 Tage'
Danke für eure Hilfe.
Gruss,
Enrique
Antworten
-
Hallo Enrique,
ja, das geht relativ einfach
SELECT * FROM dbo.DeineTable WHERE Datumsfeld >= DATEADD(day, -14, getdate() AND Datumsfeld <= DATEADD(day, -7, getdate()).
Der Vorschlag von Lutz ist nicht schlecht aber leider für Abfragen ein absoluter Killer, da durch diese Verwendung sogenannte non SARGable Abfragen generiert werden.
Erklärung und Beispiele findest Du hier:
http://db-berater.blogspot.de/2012/11/optimierung-von-datenbankmodellensargab.html
Uwe Ricken
MCSE - SQL Server 2012
MCSA - SQL Server 2012
MCITP Database Administrator 2005
MCITP Database Administrator 2008
MCITP Microsoft SQL Server 2008, Database Development
db Berater GmbH
http://www-db-berater.de
SQL Server Blog (german only)- Bearbeitet Uwe RickenMVP Dienstag, 26. Februar 2013 09:28
- Als Antwort markiert Enrique Martin Donnerstag, 28. Februar 2013 13:44
Alle Antworten
-
Am 25.02.2013 13:25, schrieb Enrique Martin:> Hallo zusammen,>> Ich möchte in einer Abfrage alle Datensätze der vorletzten Woche> ausgeben, bzw. die Datensätze der vorletzten 7 Tage.> Das würde heissen:>> ("Heute" - 7 Tage ) ("ab hier" - die folgenden 7 Tage)>> Momentan geschieht dier per OFFSET 'Anzahl der Datensätze' FETCH NEXT> 'Anzahl der Datensätze der letzten 7 Tage'Nun die aktuelle Woche bekommst du mitDATEPART(week, GETDATE())Auf die Vorletzte müsstest du mitDATEPART(week, [DatumsSpalte]) = DATEPART(week, GETDATE())-2prüfen können.Du musst allerdings noch auf den Jahreswechsel achten, da dort dievorletzte Woche auch in den 50er sein kann und der Vergleich keineTreffer bringt.Eventuell klappt dann die PrüfungDATEPART(week, [DatumsSpalte]) = DATEPART(week, GETDATE()-14)Hab ich jetzt nicht getestet ... schau mal ob das dir hilft.
-
Ja, du kannst das in der WHERE Klausel einbauen: WHERE DateColumn >= DATEADD(DAY, -7, GETDATE()) AND DateColumn <= GETDATE().
Abhängig von der genauen Anforderung solltest du evtl. den Zeitanteil aus GETDATE() und der DateColumn herausfiltern.
-- Frank Kalis Microsoft SQL Server MVP Webmaster: http://www.insidesql.org
-
Am 25.02.2013 15:56, schrieb Enrique Martin:> Hat mir leider noch nicht weitergeholfen, aber ich danke für deine Antwort.>> Kann ich dies nicht irgendwie in die WHERE-Clausel einbauen.>> WHERE DATE <= ......> AND DATE >= ........ WHERE DATEPART(week, [DATE]) = DATEPART(week, GETDATE()-14)Am Besten vielleicht den Teil DATEPART(week, GETDATE()-14) auswerten unddirekt darauf vergleichen... WHERE DATEPART(week, [DATE]) = 7Aber irgendwie bin ich noch nicht sicher welchen Datumsbereich du nunkonkret suchst.
-
Hallo Enrique,
ja, das geht relativ einfach
SELECT * FROM dbo.DeineTable WHERE Datumsfeld >= DATEADD(day, -14, getdate() AND Datumsfeld <= DATEADD(day, -7, getdate()).
Der Vorschlag von Lutz ist nicht schlecht aber leider für Abfragen ein absoluter Killer, da durch diese Verwendung sogenannte non SARGable Abfragen generiert werden.
Erklärung und Beispiele findest Du hier:
http://db-berater.blogspot.de/2012/11/optimierung-von-datenbankmodellensargab.html
Uwe Ricken
MCSE - SQL Server 2012
MCSA - SQL Server 2012
MCITP Database Administrator 2005
MCITP Database Administrator 2008
MCITP Microsoft SQL Server 2008, Database Development
db Berater GmbH
http://www-db-berater.de
SQL Server Blog (german only)- Bearbeitet Uwe RickenMVP Dienstag, 26. Februar 2013 09:28
- Als Antwort markiert Enrique Martin Donnerstag, 28. Februar 2013 13:44
-
Am 26.02.2013 10:28, schrieb Uwe Ricken:> Hallo Enrique,>> ja, das geht relativ einfach>> SELECT * FROM dbo.DeineTable> WHERE Datumsfeld >= DATEADD(day, -14, getdate() AND Datumsfeld <= DATEADD(day, -7, getdate()).>> Der Vorschlag von Lutz ist nicht schlecht aber leider für Abfragen ein> absoluter Killer, da durch diese Verwendung sogenannte non SARGable> Abfragen generiert werden.>> Erklärung und Beispiele findest Du hier:>Danke für die Info Uwe.Dann doch lieber deine Variante, wo man auch noch etwas flexibler mitdem Zeitraum sein kann.Bei meinem Vorschlag könnte man das vielleicht umgehen, wenn man eineberechnete Spalte PERSISTED anlegt - dann sollte die Abfrage auf dasFeld SARGable sein.Allerdings funktionieren nur echte Wochen, nicht 7 Tage von Mittwoch zuMittwoch.
-
Bei meinem Vorschlag könnte man das vielleicht umgehen, wenn man eineberechnete Spalte PERSISTED anlegt - dann sollte die Abfrage auf dasFeld SARGable sein.Allerdings funktionieren nur echte Wochen, nicht 7 Tage von Mittwoch zuMittwoch.
Nein, wahrscheinlich nicht. Dein Vorschlag mit der DATEPART Funktion wird (wahrscheinlich) ein Killer, weil der Optimierer einen evtl. vorhandenen Index nicht optimal nutzen kann.
Als Erklärung und in Ergänzung zu Uwe's Link, lies dir das mal in Ruhe durch: http://sqlblog.com/blogs/rob_farley/archive/2010/01/21/sargable-functions-in-sql-server.aspx
-- Frank Kalis Microsoft SQL Server MVP Webmaster: http://www.insidesql.org
-
Am 26.02.2013 11:36, schrieb Frank Kalis [MVP]:> Bei meinem Vorschlag könnte man das vielleicht umgehen, wenn man eine> berechnete Spalte PERSISTED anlegt - dann sollte die Abfrage auf das> Feld SARGable sein.> Allerdings funktionieren nur echte Wochen, nicht 7 Tage von Mittwoch zu> Mittwoch.>> Nein, wahrscheinlich nicht. Dein Vorschlag mit der DATEPART Funktion> wird (wahrscheinlich) ein Killer, weil der Optimierer einen evtl.> vorhandenen Index nicht optimal nutzen kann.Auch wenn wir jetzt etwas vom Thema abschweifen ...Ja aber das umgehe ich ja indem ich die Woche als INT abspeichere unddann einen Integer-Wert vergleiche. Die Berechnung selber erfolgt nurbei Änderung des Datensatzes.ALTER TABLE TABELLEADD COLUMN [DATE_WEEK] AS DATEPART(week, [DATE]) PERSISTED... WHERE [DATE_WEEK] = DATEPART(week, GETDATE()-14)Oder bin ich da auf dem Holzweg?
-
Hallo Lutz,
damit bist Du leider auf dem Holzweg, da datepart in Verbindung mit week einen Fehler liefert.
ALTER TABLE dbo.index_table ADD col_datecw AS DATEPART(week, coldate) PERSISTED; Msg 4936, Level 16, State 1, Line 1 Computed column 'col_datecw' in table 'index_table' cannot be persisted because the column is non-deterministic.
Dennoch ist die Idee nicht schlecht. Man kann tatsächlich mit einem Index auf einem kalkulierten Attribut arbeiten. I. d. R. wird er auch verwendet!
USE tempdb GO DROP TABLE dbo.index_table; GO CREATE TABLE dbo.index_table ( id int not null identity (1, 1), colDate datetime not null DEFAULT (DATEDIFF(dd, RAND() * 1000, getdate())) CONSTRAINT pk_index_table PRIMARY KEY CLUSTERED (id) ); SET NOCOUNT ON GO INSERT INTO dbo.index_table DEFAULT VALUES GO 10000 SELECT * FROM dbo.index_table WHERE colDate >= DATEADD(dd, -14, getdate()) AND colDate <= DATEADD(dd, -7, getdate()) CREATE INDEX ix_index_table_coldate ON dbo.index_table (coldate); SELECT * FROM dbo.index_table WHERE colDate >= DATEADD(dd, -14, getdate()) AND colDate <= DATEADD(dd, -7, getdate())
Das obige Beispiel erstellt eine einfache Tabelle führt die von mir gemachte Abfrage einmal aus. Anschließend wird ein Index auf das Attribute coldate platziert um zu zeigen, dass eine Optimierung auf diesem Attribut stattfinde. Das Ergebnis des Ausführungsplans sieht dann wie folgt aus:
Man kann sehr gut erkennen, dass bei Abfrage 1 ein Table Scan ausgeführt wird, während bei der zweiten Abfrage der zuvor gesetzte Index verwendet wird. Somit wäre das - zunächst - eine sehr gute Lösung.
Nun füge ich ein berechnetes Attribut ein (als Beispiel Jahr des Datums) und setze auf dieses Attribut eine Index. Wichtig ist dabei, dass das Attribut PERSISTED angelegt wird:
-- Now we create a persistent column which stores the datediff ALTER TABLE dbo.index_table ADD col_dateyear AS CAST(DATEPART(year, coldate) AS int) PERSISTED; CREATE INDEX ix_index_table_year ON dbo.index_table (col_dateyear);
Die Ausführung auf das Jahr 2013 sieht dann wie folgt aus:
Es wird ein INDEX-SEEK unter Verwendung des zuvor angelegten Indexes durchgeführt. Wichtig für die Ausführungstrategie ist nicht der Index allein sondern auch die Histogrammdaten aus DBCC SHOW_STATISTICS () WITH HISTOGRAM. Ist der abzufragende Bereich >= 30% der Gesamtdatenmenge, wird wieder ein Index-Scan ausgeführt!
Ob und welcher Index verwendet wird, hängt immer davon ab, wie der Index selbst definiert ist. Würde ich z. B. auch noch das Attribut coldate in die Abfrage einbeziehen, kann es sein, dass SQL Server trotz des performanten Index auf col_dateyear einen Clustered Index Scan durchführt, um so die teureren Bookmark-Lookups zu vermeiden. Das ist ein sehr komplexes Thema und ich glaube, ich sollte dazu mal was in meinem Blog schreiben :D
Uwe Ricken
MCSE - SQL Server 2012
MCSA - SQL Server 2012
MCITP Database Administrator 2005
MCITP Database Administrator 2008
MCITP Microsoft SQL Server 2008, Database Development
db Berater GmbH
http://www-db-berater.de
SQL Server Blog (german only)- Bearbeitet Uwe RickenMVP Dienstag, 26. Februar 2013 13:00
-
Am 26.02.2013 13:59, schrieb Uwe Ricken:> Hallo Lutz,>> damit bist Du leider auf dem Holzweg, da datepart in Verbindung mit week> einen Fehler liefert.>> ALTER TABLE dbo.index_table> ADD col_datecw AS DATEPART(week, coldate) PERSISTED;> Msg 4936, Level 16, State 1, Line 1> Computed column 'col_datecw' in table 'index_table' cannot be persisted because the column is non-deterministic.Daran habe ich gar nicht gedacht, habe es aber ehrlich gesagt auch nichtausprobiert. Ursache wird die Abhängigkeit von SET DATEFIRST sein.Aber selbst da gibt es Abhilfe:DATEPART(iso_week, coldate) funktioniert als permanente berechnete Spalte.> Dennoch ist die Idee nicht schlecht. Man kann tatsächlich mit einem> Index auf einem kalkulierten Attribut arbeiten. I. d. R. wird er auch> verwendet!>> ... ausführliche Abhandlung zum Thema ;)>> Das ist> ein sehr komplexes Thema und ich glaube, ich sollte dazu mal was in> meinem Blog schreiben :DDanke für die Ausführungen und einen Blog-Eintrag dazu kann ich nurbegrüßen ;)
-
Am 26.02.2013 11:36, schrieb Frank Kalis [MVP]:> Bei meinem Vorschlag könnte man das vielleicht umgehen, wenn man eine> berechnete Spalte PERSISTED anlegt - dann sollte die Abfrage auf das> Feld SARGable sein.> Allerdings funktionieren nur echte Wochen, nicht 7 Tage von Mittwoch zu> Mittwoch.>> Nein, wahrscheinlich nicht. Dein Vorschlag mit der DATEPART Funktion> wird (wahrscheinlich) ein Killer, weil der Optimierer einen evtl.> vorhandenen Index nicht optimal nutzen kann.Auch wenn wir jetzt etwas vom Thema abschweifen ...Ja aber das umgehe ich ja indem ich die Woche als INT abspeichere unddann einen Integer-Wert vergleiche. Die Berechnung selber erfolgt nurbei Änderung des Datensatzes.ALTER TABLE TABELLEADD COLUMN [DATE_WEEK] AS DATEPART(week, [DATE]) PERSISTED... WHERE [DATE_WEEK] = DATEPART(week, GETDATE()-14)Oder bin ich da auf dem Holzweg?
-- Frank Kalis Microsoft SQL Server MVP Webmaster: http://www.insidesql.org