2016-04-24 55 views
-1

嗨:在MSSQL/TSQL中,場景:假設今天的日期是'2016-01-15'(2016年1月15日)。我想在過去的10年中搜索數據,但需要30天的時間。因此,搜索範圍將爲:從12月15日到2月15日,但不僅僅是從上述日期起搜索+30天(2015年12月15日至2016年2月15日),我只想在12月15日之間搜索所有數據以及過去10年的2月15日。搜索+ - 根據今天的日期計算過去n年中的日期和月份範圍

爲了進行分析,我正在尋找天氣模式,因此我需要堅持在過去的n年中每年的相同時間框架。

+1

我刪除了無關的數據庫標記。 –

+1

mysql,mariadb或mssql? –

+2

歡迎來到Stackoverflow。如果您顯示迄今爲止已嘗試過的內容,則可以改進此問題,它可以幫助人們回答如果您向他們提供一些開始的代碼,請參閱https://stackoverflow.com/help/how-to-ask以瞭解如何詢問好問題。 –

回答

0

這將MS ​​SQL Server上運行。歡迎您的修改。

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

像這樣的東西應該做的伎倆:

;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 

編輯:我不知道你會怎麼你的WHERE子句中有這樣的,最好的,我能做的就是內聯函數,那麼你可以做一個內與它連接:

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) 

然後你就可以內部連接就像任何其他表

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

哪會過濾出你需要的行。

+0

你的解決方案有一個硬編碼的數字可以搜索多少年。我以我的問題中提到的10年爲例。根據我正在研究的內容,年數取決於我正在搜索的數據庫。我希望有一個答案,我不必手動調整或硬編碼任何數字。該查詢只需要我的日期和我想要的天數範圍,然後在該數據庫中每年搜索該範圍。儘管感謝您的回覆。也許我可以嘗試修改你的想法。 – Bobby

+0

當然,您可以創建一個存儲過程並對解決方案進行參數化,這只是一個如何獲取所需數據集的一般想法。將年份範圍替換爲-9,月份範圍爲-1/1,開始日期爲'2016-01-15'。如果你想加快這個查詢在t.date列上創建索引並在其中包含ID列。 – Bistabil

+0

我也希望解決方案的where子句的形式,因爲它是我的查詢已經很大。謝謝 – Bobby

0

是可變的,驅動作爲存儲過程的另一個潛在的解決方案...

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

這有效。

首先,我創建了三個變量,一個用於日期,一個用於日間間隔,另一個用於年份間隔。

然後,我創建了2個臨時表,其中一個是他們的日子和月份,另一個是可能的一年。

然後,只需將兩個臨時表內部連接到所選表格即可。

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