2016-04-24 8 views
-1

Hallo: In MSSQL/TSQL ist hier das Szenario: Sagen wir, das heutige Datum ist '2016-01-15' (15. Januar 2016). Ich möchte Daten für + - 30 Tage, aber für die letzten 10 Jahre suchen. Daher wäre der Suchbereich: 15. Dezember bis 15. Februar, aber anstatt einfach nur nach + 30 Tagen (15. Dezember 2015 bis 15. Februar 2016) vom oben genannten Datum zu suchen, möchte ich nur zwischen dem 15. Dezember nach allen Daten suchen und 15. Februar für die letzten 10 Jahre.Suche + - Tag und Monat Bereich in den letzten Jahren basierend auf dem heutigen Datum

Um zu relativieren, suche ich nach Wettermustern, daher muss ich in den letzten n Jahren in der Nähe des gleichen Zeitrahmens für jedes Jahr bleiben.

+1

Ich entfernte die externen Datenbank-Tags. –

+1

mysql, mariadb oder mssql? –

+2

Willkommen bei Stackoverflow. Diese Frage könnte verbessert werden, wenn Sie zeigen, was Sie bisher versucht haben, es hilft den Leuten zu antworten, wenn Sie ihnen etwas Code geben, um mit zu beginnen, sehen https://stackoverflow.com/help/how-to-ask für, wie man a fragt gute Frage. –

Antwort

0

Das auf MS SQL Server arbeiten. Ihre Änderungen sind willkommen.

create procedure dbo.weather 
@myDate datetime, 
@monthInterval int=1, 
@yearsToSearch int=10 
as 
declare @startDate datetime=dateadd(month,[email protected],@myDate), 
@endDate datetime=dateadd(month,@monthInterval,@myDate), 
@cnt int=0 

declare @tmp table(<your def here>) 

while @cnt<[email protected] 
begin 
insert @tmp(<field list here>) 
select <field list here> from <your_table_here> 
where <dateField> between @startDate and @endDate 

select @startDate=DATEADD(year,-1,@startDate),@endDate=DATEADD(year,-1,@endDate),@[email protected]+1 
end 

select * from @tmp 
0

So etwas sollte es tun:

;WITH CTE1(StartDate,EndDate) AS 
(
    SELECT 
     DATEADD(MONTH,-1,'2016-01-15') AS startDate 
     , DATEADD(MONTH,1,'2016-01-15') AS EndDate 
    UNION ALL 
    SELECT 
     DATEADD(YEAR,-1,startDate) 
     , DATEADD(YEAR,-1,EndDate) 
    FROM CTE1 
    WHERE CTE1.StartDate > DATEADD(YEAR,-9,'2016-01-15') 
), CTE2 AS (
    SELECT DISTINCT columnIDs 
    FROM table t 
    INNER JOIN cte1 c ON t.date BETWEEN c.StartDate and c.EndDate 
) 
SELECT * 
FROM table t 
INNER JOIN cte2 c ON t.columnID = c.columnIDs 

edit: Ich weiß nicht, wie würden Sie diese haben in der Where-Klausel, am besten ich tun kann Inline-Funktion ist, dann kann man eine innere tun verbinden mit ihm:

CREATE FUNCTION dbo.fn_weather (@startDate datetime, @YearRange int, @MonthRange int) 
RETURNS table 
AS 
RETURN 
(WITH CTE1(StartDate,EndDate) AS 
(
    SELECT 
     DATEADD(MONTH, -1*@MonthRange, @startDate) AS startDate 
     , DATEADD(MONTH, @MonthRange, @startDate) AS EndDate 
    UNION ALL 
    SELECT 
     DATEADD(YEAR,-1,startDate) 
     , DATEADD(YEAR,-1,EndDate) 
    FROM CTE1 
    WHERE CTE1.StartDate > DATEADD(YEAR, -1*(@YearRange-1), @startDate) 
) 
SELECT DISTINCT ID 
FROM table AS t 
INNER JOIN cte1 c ON t.date BETWEEN c.startDate AND c.EndDate) 

Dann können Sie innere wie jede andere Tabelle

INNER JOIN dbo.fn_weather(GETDATE(),10,1) AS fnw ON fnw.ID = table.ID 

verbinden, die filtert die Zeilen aus, die Sie benötigen.

+0

Ihre Lösung hat eine fest codierte Nummer, nach der für viele Jahre gesucht werden kann. Ich habe 10 Jahre in meiner Frage als Beispiel erwähnt. Je nachdem, was ich recherchiere, hängt die Anzahl der Jahre davon ab, welche Datenbank ich suche. Ich habe auf eine Antwort gehofft, wo ich keine Zahlen manuell einstellen oder hart codieren muss.Die Abfrage würde nur mein Datum und wie viele + - Tage reichen, die ich will, und dann eine Suche nach diesem Bereich für jedes Jahr in dieser Datenbank machen. Danke für Ihre Antwort. Vielleicht kann ich versuchen, deine Idee zu ändern. – Bobby

+0

Natürlich können Sie eine gespeicherte Prozedur erstellen und die Lösung parametrisieren, dies ist nur eine allgemeine Idee, wie Sie das benötigte Dataset erhalten. Ersetzen Sie den Wert -9 durch den Jahresbereich, -1/1 durch den Monat, '2016-01-15' mit Startdatum. Wenn Sie diese Abfrage beschleunigen möchten, erstellen Sie den Index in der Spalte "t.date" und fügen Sie die ID-Spalte darin ein. – Bistabil

+0

Ich hatte auch gehofft, die Lösung in Form einer Where-Klausel zu haben, da es meine Anfrage schon sehr groß ist. Danke – Bobby

0

Eine andere mögliche Lösung, die variabel als gespeicherte Prozedur angetrieben ist ...

CREATE PROCEDURE GetRecordsFromDateRange 
    @StartDate as Date, 
    @EndDate as Date, 
    @numYearsBack as int 
as 
BEGIN 

Declare @useStartDate Date 
Declare @useEndDate Date 
Set @useStartDate = DATEADD(month,-1,@StartDate) 
Set @useEndDate = DATEADD(month,1,@EndDate) 

Select 
    Data Fields 
From table t 
Where 
    MONTH(t.TableDateColumn) >= MONTH(@useStartDate) 
    AND MONTH(t.TableDateColumn) <= MONTH(@useEndDate) 
    AND YEAR(t.TableDateColumn) >= YEAR(@useEndDate) - @numYearsBack 

END 
0

Das funktioniert.

Zuerst erstelle ich drei Variablen, eine für Ihr Datum, eine für Ihr Tages-Intervall und eine für Ihr Jahres-Intervall.

Dann erstelle ich 2 temporäre Tabellen, eine mit den Tagen und Monaten und eine mit dem möglichen Jahr.

Dann nur inner-verbinden Sie die beiden Temp-Tabellen zu Ihrer ausgewählten Tabelle.

DECLARE @Date AS DATETIME = '2016-01-15' 
DECLARE @YearInterval AS INT = 10 
DECLARE @DayInterval AS INT = 30 

;WITH DayMonthCTE AS (
SELECT 
    DATEADD(d, [email protected], @Date) AS myDate 
UNION ALL 
SELECT 
    DATEADD(DAY, 1, myDate) AS myDate 
FROM 
    DayMonthCTE 
WHERE 
    DATEADD(DAY, 1, myDate) <= DATEADD(d, @DayInterval, @Date) 
) 

SELECT 
    FORMAT(myDate, 'dd-MM') AS [dayMonth] 
INTO 
    #DateRange 
FROM 
    DayMonthCTE 
OPTION 
    (MAXRECURSION 0) 


;WITH YearCTE AS (
SELECT 
    YEAR(@Date) - @YearInterval AS myYear 
UNION ALL 
SELECT 
    myYear + 1 
FROM 
    YearCTE 
WHERE 
    myYear < YEAR(@Date) 
) 

SELECT 
    myYear AS [Year] 
INTO 
    #YearRange 
FROM 
    YearCTE 

SELECT 
    * 
FROM 
    YOURTABLE AS D 
    INNER JOIN #DateRange AS DR ON FORMAT(D.Date, 'dd-MM') = DR.dayMonth 
    INNER JOIN #YearRange AS YR ON YEAR(D.Date) = YR.Year 
Verwandte Themen