嗨:在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年中每年的相同時間框架。
嗨:在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年中每年的相同時間框架。
這將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
像這樣的東西應該做的伎倆:
;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
哪會過濾出你需要的行。
你的解決方案有一個硬編碼的數字可以搜索多少年。我以我的問題中提到的10年爲例。根據我正在研究的內容,年數取決於我正在搜索的數據庫。我希望有一個答案,我不必手動調整或硬編碼任何數字。該查詢只需要我的日期和我想要的天數範圍,然後在該數據庫中每年搜索該範圍。儘管感謝您的回覆。也許我可以嘗試修改你的想法。 – Bobby
當然,您可以創建一個存儲過程並對解決方案進行參數化,這只是一個如何獲取所需數據集的一般想法。將年份範圍替換爲-9,月份範圍爲-1/1,開始日期爲'2016-01-15'。如果你想加快這個查詢在t.date列上創建索引並在其中包含ID列。 – Bistabil
我也希望解決方案的where子句的形式,因爲它是我的查詢已經很大。謝謝 – Bobby
是可變的,驅動作爲存儲過程的另一個潛在的解決方案...
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
這有效。
首先,我創建了三個變量,一個用於日期,一個用於日間間隔,另一個用於年份間隔。
然後,我創建了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
我刪除了無關的數據庫標記。 –
mysql,mariadb或mssql? –
歡迎來到Stackoverflow。如果您顯示迄今爲止已嘗試過的內容,則可以改進此問題,它可以幫助人們回答如果您向他們提供一些開始的代碼,請參閱https://stackoverflow.com/help/how-to-ask以瞭解如何詢問好問題。 –