Ich möchte die Datensätze des letzten Monats basierend auf meinem Feld "date_created" in der Datenbanktabelle [member] abrufen.
Was ist die SQL, um dies zu tun?
Zur Verdeutlichung im letzten Monat - 08.01.2009 bis 31.8.2009
Wenn heute der 01.03.2010 ist, muss ich die Aufzeichnungen vom 12.01.2009 bis zum 31.12.2009 erhalten.
sql
sql-server
tsql
Billy
quelle
quelle
DATEDIFF(month, date_created, GETDATE()) = 1
? Würde das nicht auch funktionieren?Antworten:
SELECT * FROM Member WHERE DATEPART(m, date_created) = DATEPART(m, DATEADD(m, -1, getdate())) AND DATEPART(yyyy, date_created) = DATEPART(yyyy, DATEADD(m, -1, getdate()))
Sie müssen den Monat und das Jahr überprüfen.
quelle
SELECT * FROM Member WHERE DATEPART(m, date_created) = DATEPART(m, DATEADD(m, -1, getdate())) AND DATEPART(yy, date_created) = DATEPART(yy, DATEADD(m, -1, getdate()))
funktioniert perfektAlle vorhandenen (Arbeits-) Antworten haben eines von zwei Problemen:
1. Ignorierte Indizes:
Wenn für eine durchsuchte Spalte eine Funktion aufgerufen wird (einschließlich implizit wie für
CAST
), muss der Optimierer zum größten Teil die Indizes in der Spalte ignorieren und jeden Datensatz durchsuchen. Hier ist ein kurzes Beispiel:Wir haben es mit Zeitstempeln zu tun, und die meisten RDBMS speichern diese Informationen in der Regel als zunehmenden Wert, normalerweise als
long
oderBIGINTEGER
in Milli- / Nanosekunden. Die aktuelle Zeit sieht also so aus / wird wie folgt gespeichert:1402401635000000 -- 2014-06-10 12:00:35.000000 GMT
Sie sehen dort nicht den 'Year'-Wert (
'2014'
), oder? Tatsächlich gibt es einiges an komplizierter Mathematik, die man hin und her übersetzen kann. Wenn Sie also eine der Extraktions- / Datumsteilfunktionen in der gesuchten Spalte aufrufen, muss der Server all diese Berechnungen durchführen, um herauszufinden, ob Sie sie in die Ergebnisse aufnehmen können. Bei kleinen Tabellen ist dies kein Problem, aber wenn der Prozentsatz der ausgewählten Zeilen abnimmt, wird dies zu einem immer größeren Abfluss. Dann machen Sie es in diesem Fall ein zweites Mal, um nachMONTH
... zu fragen. Nun , Sie bekommen das Bild.2. Unbeabsichtigte Daten:
Abhängig von der jeweiligen Version von SQL Server und Datentypen von Spalten, mit
BETWEEN
(oder ähnlich inklusive oberen gebundenen Bereichen:<=
) kann in den falschen Daten führen ausgewählt werden . Im Wesentlichen können Sie Daten ab Mitternacht des "nächsten" Tages einschließen oder einen Teil der Aufzeichnungen des "aktuellen" Tages ausschließen.Was Sie sollten dabei sein:
Wir brauchen also einen Weg, der für unsere Daten sicher ist und Indizes verwendet (falls möglich). Der richtige Weg ist dann von der Form:
Da es nur einen Monat gibt,
@startOfPreviousMonth
kann es leicht ersetzt werden durch:Wenn Sie den Beginn des aktuellen Monats auf dem Server ableiten müssen, können Sie dies folgendermaßen tun:
Ein kurzes Wort zur Erklärung hier. Die Initiale
DATEDIFF(...)
wird den Unterschied zwischen dem Beginn der aktuellen Ära (0001-01-01
- AD, CE, was auch immer) erkennen und im Wesentlichen eine große ganze Zahl zurückgeben. Dies ist die Anzahl der Monate bis zum Beginn des aktuellen Monats. Wir addieren diese Zahl dann zum Beginn der Ära, die zu Beginn des jeweiligen Monats liegt.Ihr vollständiges Skript könnte / sollte also wie folgt aussehen:
DECLARE @startOfCurrentMonth DATETIME SET @startOfCurrentMonth = DATEADD(month, DATEDIFF(month, 0, CURRENT_TIMESTAMP), 0) SELECT * FROM Member WHERE date_created >= DATEADD(month, -1, @startOfCurrentMonth) -- this was originally misspelled AND date_created < @startOfCurrentMonth
Alle Datumsoperationen werden daher nur einmal mit einem Wert ausgeführt. Dem Optimierer steht es frei, Indizes zu verwenden, und es werden keine falschen Daten aufgenommen.
quelle
Wenn Sie die bisher bereitgestellten Optionen hinzufügen, werden Ihre Indizes überhaupt nicht verwendet.
So etwas reicht aus und verwendet einen Index für die Tabelle (falls vorhanden).
DECLARE @StartDate DATETIME, @EndDate DATETIME SET @StartDate = dateadd(mm, -1, getdate()) SET @StartDate = dateadd(dd, datepart(dd, getdate())*-1, @StartDate) SET @EndDate = dateadd(mm, 1, @StartDate) SELECT * FROM Member WHERE date_created BETWEEN @StartDate AND @EndDate
quelle
DECLARE @StartDate DATETIME, @EndDate DATETIME SET @StartDate = DATEADD(mm, DATEDIFF(mm,0,getdate())-1, 0) SET @EndDate = DATEADD(mm, 1, @StartDate) SELECT * FROM Member WHERE date_created BETWEEN @StartDate AND @EndDate
Ein Upgrade auf die Lösung von mrdenny, auf diese Weise erhalten Sie genau den letzten Monat von JJJJ-MM-01
quelle
Letzter Monat gilt als bis zum letzten Tag des Monats. Der letzte Tag des Monats ist der 31. Januar, was nicht den letzten 30 Tagen entspricht.
SELECT CONVERT(DATE, DATEADD(DAY,-DAY(GETDATE()),GETDATE()))
quelle
Eine Möglichkeit hierfür ist die Verwendung der DATEPART- Funktion:
select field1, field2, fieldN from TABLE where DATEPART(month, date_created) = 4 and DATEPART(year, date_created) = 2009
wird alle Daten im April zurückgeben. Für den letzten Monat (dh vor dem aktuellen Monat) können Sie auch GETDATE und DATEADD verwenden :
select field1, field2, fieldN from TABLE where DATEPART(month, date_created) = (DATEPART(month, GETDATE()) - 1) and DATEPART(year, date_created) = DATEPART(year, DATEADD(m, -1, GETDATE()))
quelle
declare @PrevMonth as nvarchar(256) SELECT @PrevMonth = DateName( month,DATEADD(mm, DATEDIFF(mm, 0, getdate()) - 1, 0)) + '-' + substring(DateName( Year, getDate() ) ,3,4)
quelle
SQL-Abfrage, um nur den aktuellen Monat aufzuzeichnen
SELECT * FROM CUSTOMER WHERE MONTH(DATE) = MONTH(CURRENT_TIMESTAMP) AND YEAR(DATE) = YEAR(CURRENT_TIMESTAMP);
quelle
select * from [member] where DatePart("m", date_created) = DatePart("m", DateAdd("m", -1, getdate())) AND DatePart("yyyy", date_created) = DatePart("yyyy", DateAdd("m", -1, getdate()))
quelle
DECLARE @StartDate DATETIME, @EndDate DATETIME SET @StartDate = DATEADD(mm, DATEDIFF(mm, 0, getdate()) - 1, 0) SET @EndDate = dateadd(dd, -1, DATEADD(mm, 1, @StartDate)) SELECT * FROM Member WHERE date_created BETWEEN @StartDate AND @EndDate
und ein weiteres Upgrade auf die Lösung von mrdenny.
Es gibt auch den genauen letzten Tag des Vormonats an.
quelle
quelle
Ich bin von Oracle env und würde es in Oracle so machen:
select * from table where trunc(somedatefield, 'MONTH') = trunc(sysdate -INTERVAL '0-1' YEAR TO MONTH, 'MONTH')
Idee: Ich führe einen geplanten Bericht des Vormonats aus (vom ersten Tag bis zum letzten Tag des Monats, ohne Fenster). Dies könnte indexunfreundlich sein, aber Oracle hat sowieso eine schnelle Datumsabwicklung. Gibt es einen ähnlichen einfachen und kurzen Weg in MS SQL? Die Antwort, bei der Jahr und Monat getrennt verglichen werden, erscheint Oracle-Leuten albern.
quelle
Mit dieser Abfrage können Sie die Datensätze des letzten Monats abrufen
SELECT * FROM dbo.member d WHERE CONVERT(DATE, date_created,101)>=CONVERT(DATE,DATEADD(m, datediff(m, 0, current_timestamp)-1, 0)) and CONVERT(DATE, date_created,101) < CONVERT(DATE, DATEADD(m, datediff(m, 0, current_timestamp)-1, 0),101)
quelle
Ich denke nicht, dass die akzeptierte Lösung sehr indexfreundlich ist. Ich verwende stattdessen die folgenden Zeilen
select * from dbtable where the_date >= convert(varchar(10),DATEADD(m, -1, dateadd(d, - datepart(dd, GETDATE())+1, GETDATE())),120) and the_date <= dateadd(ms, -3, convert(varchar(10),DATEADD(m, 0, dateadd(d, - datepart(dd, GETDATE())+1, GETDATE())),120));
Oder einfach (das ist das Beste).
select * from dbtable where the_date >= convert(varchar(10),DATEADD(m, -1, dateadd(d, - datepart(dd, GETDATE())+1, GETDATE())),120) and the_date < SELECT convert(varchar(10),DATEADD(m, -1, dateadd(d, - datepart(dd, GETDATE())+1, GETDATE())),120);
Etwas Hilfe
-- Get the first of last month SELECT convert(varchar(10),DATEADD(m, -1, dateadd(d, - datepart(dd, GETDATE())+1, GETDATE())),120); -- Get the first of current month SELECT convert(varchar(10),DATEADD(m, -1, dateadd(d, - datepart(dd, GETDATE())+1, GETDATE())),120); --Get the last of last month except the last 3milli seconds. (3miliseconds being used as SQL express otherwise round it up to the full second (SERIUSLY MS) SELECT dateadd(ms, -3, convert(varchar(10),DATEADD(m, 0, dateadd(d, - datepart(dd, GETDATE())+1, GETDATE())),120));
quelle
Auf dem SQL Server für den letzten Monat:
select * from tablename where order_date > DateAdd(WEEK, -1, GETDATE()+1) and order_date<=GETDATE()
quelle
DECLARE @curDate INT = datepart( Month,GETDATE()) IF (@curDate = 1) BEGIN select * from Featured_Deal where datepart( Month,Created_Date)=12 AND datepart(Year,Created_Date) = (datepart(Year,GETDATE())-1) END ELSE BEGIN select * from Featured_Deal where datepart( Month,Created_Date)=(datepart( Month,GETDATE())-1) AND datepart(Year,Created_Date) = datepart(Year,GETDATE()) END
quelle
DECLARE @StartDate DATETIME, @EndDate DATETIME SET @StartDate = dateadd(mm, -1, getdate()) SET @StartDate = dateadd(dd, datepart(dd, getdate())*-1, @StartDate) SET @EndDate = dateadd(mm, 1, @StartDate) set @StartDate = DATEADD(dd, 1 , @StartDate)
quelle
Ich habe ein ähnliches Problem behoben, indem ich meinem SELECT- Teil Month hinzugefügt habe
und als ich WHERE Anweisung hinzugefügt habe
quelle
Wenn Sie nach dem letzten Monat suchen, versuchen Sie dies,
SELECT FROM #emp WHERE DATEDIFF(MONTH,CREATEDDATE,GETDATE()) = 1
Wenn Sie nach dem letzten Monat suchen, versuchen Sie dies,
SELECT FROM #emp WHERE DATEDIFF(day,CREATEDDATE,GETDATE()) between 1 and 30
quelle
Eine einfache Abfrage, die für mich funktioniert, ist:
Wählen Sie * aus der Tabelle aus, in der DATEADD (Monat, 1, DATEFIELD)> = getdate ()
quelle
Wenn Sie nach Daten des Vormonats suchen:
Dies funktioniert auch, wenn sich das Jahr ändert. Es wird auch auf MySQL funktionieren.
quelle