WHERE-Klausel, um alle Datensätze in einem bestimmten Monat zu finden

86

Ich möchte in der Lage sein, einer gespeicherten Prozedur einen Monat und ein Jahr zuzuweisen und alles zurückzugeben, was in diesem Monat passiert. Wie mache ich das, da ich nicht vergleichen kann, da einige Monate eine unterschiedliche Anzahl von Tagen usw. haben?

Was ist der beste Weg, dies zu tun? Kann ich nur nach Vergleichen nach Jahr und Monat fragen?

Vielen Dank.

Tarks
quelle

Antworten:

186

Ich denke, die Funktion, die Sie suchen, ist MONTH(date). Sie werden wahrscheinlich auch 'YEAR' verwenden wollen .

Nehmen wir an, Sie haben eine Tabelle mit dem Namen things:

id happend_at
-- ----------------
1  2009-01-01 12:08
2  2009-02-01 12:00
3  2009-01-12 09:40
4  2009-01-29 17:55

happened_atAngenommen , Sie möchten ausführen, um alle Datensätze zu finden, die im Monat 2009/01 (Januar 2009) einen haben. Die SQL-Abfrage wäre:

SELECT id FROM things 
   WHERE MONTH(happened_at) = 1 AND YEAR(happened_at) = 2009

Welches würde zurückkehren:

id
---
1
3
4
Shalom Craimer
quelle
14
Tatsächlich ! Für alle Interessierten "Die Funktionen DAY, MONTH und YEAR sind Synonyme für DATEPART (TT, Datum), DATEPART (MM, Datum) und DATEPART (JJ, Datum)."
Tarks
16

Die Verwendung der in den meisten Antworten vorgeschlagenen Funktionen MONTH und YEAR hat den Nachteil, dass SQL Server keinen Index für Ihre Datumsspalte verwenden kann. Dies kann die Leistung auf einem großen Tisch beeinträchtigen.

Ich würde gerne einen DATETIME-Wert (z. B. @StartDate) an die gespeicherte Prozedur übergeben, die den ersten Tag des Monats darstellt, an dem Sie interessiert sind.

Sie können dann verwenden

SELECT ... FROM ...
WHERE DateColumn >= @StartDate 
AND DateColumn < DATEADD(month, 1, @StartDate)

Wenn Sie den Monat und das Jahr als separate Parameter an die gespeicherte Prozedur übergeben müssen, können Sie mit CAST und CONVERT eine DATETIME generieren, die den ersten Tag des Monats darstellt. Gehen Sie dann wie oben vor. Wenn Sie dies tun, würde ich empfehlen, eine Funktion zu schreiben, die eine DATETIME aus ganzzahligen Werten für Jahr, Monat und Tag generiert, z. B. die folgenden aus einem SQL Server-Blog .

create function Date(@Year int, @Month int, @Day int)
returns datetime
as
    begin
    return dateadd(month,((@Year-1900)*12)+@Month-1,@Day-1)
    end
go

Die Abfrage lautet dann:

SELECT ... FROM ...
WHERE DateColumn >= Date(@Year,@Month,1)
AND DateColumn < DATEADD(month, 1, Date(@Year,@Month,1))
Joe
quelle
1
Ja, ich stimme @joe zu. "Die Verwendung der in den meisten Antworten vorgeschlagenen Funktionen MONTH und YEAR hat den Nachteil, dass SQL Server keinen Index für Ihre Datumsspalte verwenden kann. Dies kann die Leistung einer großen Tabelle beeinträchtigen . "
Raghav
Könnte ich etwas hinzufügen? Wenn Sie '@StartDate in einem Parameter deklarieren, würde ich auch' @EndDate deklarieren und das DATEADD dort platzieren, anstatt SQL die Mathematik in jeder Zeile ausführen zu lassen.
DataGirl
@ DataGirl - interessanter Punkt. Ich hatte angenommen, dass die DATEADD-Funktion als Laufzeitkonstante behandelt und nur einmal ausgewertet wird. Wenn diesbezüglich Zweifel bestehen, @EndDatewird dies durch die Deklaration deutlich.
Joe
3

Als Alternative zu den Funktionen MONTH und YEAR funktioniert auch eine reguläre WHERE-Klausel:

select *
from yourtable
where '2009-01-01' <= datecolumn and datecolumn < '2009-02-01'
Andomar
quelle
3

Mehr ein Tipp sehr einfach. Sie können auch die Funktion to_char verwenden.

Für Monat:

to_char (passiert_at, 'MM') = 01

Für Jahr:
to_char (passiert_at, 'JJJJ') = 2009

Für Tag:

to_char (passiert_at, 'DD') = 01

Die Funktion to_char wird von der SQL-Sprache und nicht von einer bestimmten Datenbank unterstützt.

Ich hoffe, jemand mehr helfen ...

Abs!

Marcelo Rebouças
quelle
1
Ich habe den Eindruck, dass dies nur für Oracle funktioniert, es ist wirklich spezifisch. SQL Server unterstützt dies definitiv nicht.
Carol
1

Kann ich nur nach Vergleichen nach Jahr und Monat fragen?

Sie können. Hier ist ein einfaches Beispiel mit der AdventureWorks-Beispieldatenbank ...

DECLARE @Year       INT
DECLARE @Month      INT

SET @Year = 2002
SET @Month = 6

SELECT 
    [pch].* 
FROM 
    [Production].[ProductCostHistory]   pch
WHERE
    YEAR([pch].[ModifiedDate]) = @Year
AND MONTH([pch].[ModifiedDate]) = @Month
Der faule DBA
quelle
1

Ich finde es einfacher, einen Wert als zeitlichen Datentyp (z. B. DATETIME) zu übergeben und dann die zeitliche Funktionalität zu verwenden, insbesondere DATEADDund DATEPART, um das Start- und Enddatum für den Zeitraum zu finden, in diesem Fall den Monat, z. B. das Paar aus Startdatum und Enddatum Ersetzen CURRENT_TIMESTAMPSie für den aktuellen Monat einfach DATETIMEIhren Parameter vom Typ (beachten Sie, dass der Wert für 1990-01-01 völlig willkürlich ist):

SELECT DATEADD(M, 
          DATEDIFF(M, '1990-01-01T00:00:00.000', CURRENT_TIMESTAMP), 
          '1990-01-01T00:00:00.000'), 
       DATEADD(M, 
          DATEDIFF(M, '1990-01-01T00:00:00.000', CURRENT_TIMESTAMP), 
          '1990-01-31T23:59:59.997')
eines Tages, wenn
quelle
0

So etwas sollte es tun:

select * from yourtable where datepart(month,field) = @month and datepart(year,field) = @year

Alternativ können Sie Monat und Jahr beim Erstellen des Datensatzes in eigene Spalten aufteilen und dann gegen diese auswählen.

Iain

Tempel
quelle
0

Eine Möglichkeit wäre, eine Variable zu erstellen, die den ersten des Monats darstellt (dh den 01.05.2009), sie entweder an den Prozess zu übergeben oder zu erstellen (Monat / 1 / Jahr verketten). Verwenden Sie dann die DateDiff-Funktion.

WHERE DateDiff(m,@Date,DateField) = 0

Dies gibt alles mit einem passenden Monat und Jahr zurück.

Mike Bennett
quelle
-4
SELECT * FROM yourtable WHERE yourtimestampfield LIKE 'AAAA-MM%';

Wo AAAAist das Jahr, das Sie wollen und wo MMist der Monat, den Sie wollen

user2022742
quelle