2017-02-22 66 views
0

我正在尋找一些T-SQL代碼,應該選擇「從當前日期返回的一年(與一月份的上個星期天同一時間)」。T-SQL date pickup

我這是在SQL Server 2014中使用了一些T-SQL代碼:

select 
    convert(varchar(10), DATEADD(day, DATEDIFF(day, '19000107', DATEADD(month, DATEDIFF(MONTH, 0, CONVERT(date, CONVERT(VARCHAR(4), (CASE WHEN MONTH(GetDate()) = 1 THEN CONVERT(VARCHAR(4), GetDate(), 112) - 1 ELSE CONVERT(VARCHAR(4), GetDate(), 112) END), 112) + '0101')), 30))/7 * 7, '19000107'), 120) 

上面的代碼精選本年度的日期(上週日一月月)。但是我希望T-SQL代碼選擇去年(1月份的上個星期日)的日期。

詳情 - 我希望T-SQL代碼從下表

Current day    Expected result 
--------------------------------------- 
2017-02-05    2016-01-31 
2017-01-05    2015-01-25 
2018-02-19    2017-01-29 
2018-01-19    2016-01-31 
2019-02-28    2018-01-28 

產生預期的結果請注意總是一年「上週日在一月月」啓動。

回答

3

將會有更簡潔的解決方案,但是,當我們假設你的代碼是經過時間考驗的和穩健的,我只想通過,現在是負一一年表達式替換GETDATE()

DATEADD(year, -1, GETDATE()) 

因此:

SELECT 
    convert(varchar(10), DATEADD(day, DATEDIFF(day, '19000107', DATEADD(month, DATEDIFF(MONTH, 0, CONVERT(date, CONVERT(VARCHAR(4), (CASE WHEN MONTH(DATEADD(year,-1,GetDate())) = 1 THEN CONVERT(VARCHAR(4), DATEADD(year,-1,GetDate()), 112) - 1 ELSE CONVERT(VARCHAR(4), DATEADD(year,-1,GetDate()), 112) END), 112) + '0101')), 30))/7 * 7, '19000107'), 120) 
+0

非常好的工作感謝 – user2331670

0

這將封鎖具有數據的列。

請給它一個嘗試讓我知道。謝謝。

select 
    convert(varchar(10), DATEADD(day, DATEDIFF(day, '19000107', DATEADD(month, DATEDIFF(MONTH, 0, CONVERT(date, CONVERT(VARCHAR(4), (CASE WHEN MONTH(GetDate()) = 1 THEN CONVERT(VARCHAR(4), GetDate(), 112) - 1 ELSE CONVERT(VARCHAR(4), 
GetDate(), 112) END), 112) + '0101')), 30))/7 * 7, '19000107'), 120) AS CurrentDay , convert(varchar(10), DATEADD(day, DATEDIFF(day, '19000107', DATEADD(month, DATEDIFF(MONTH, 0, CONVERT(date, CONVERT(VARCHAR(4), (CASE WHEN MONTH(DATEADD(year,-1,GetDate())) = 1 THEN CONVERT(VARCHAR(4), DATEADD(year,-1,GetDate()), 112) - 1 ELSE CONVERT(VARCHAR(4), 
DATEADD(year,-1,GetDate()), 112) END), 112) + '0101')), 30))/7 * 7, '19000107'), 120) as ExpectedResult 
+0

謝謝,但@@@ dlatikay答案工作 – user2331670

+0

沒有問題@ user2331670 – FreedomPride

3

如果你有一個日曆表,你可以跳過第一CTE(也可能是MAXRECURSION選項),只是使用日曆表。但願這是顯然是正確的

declare @today date 
set @today = CURRENT_TIMESTAMP 

;With Dates as (
    select CONVERT(date,'19000101') as d 
    union all 
    select DATEADD(day,1,d) from Dates where d < '21000101' 
), ApplicableSundays as (
    select d,ROW_NUMBER() OVER (ORDER BY d desc) as rn 
    from Dates 
    where d < @today and 
    DATEPART(month,d) = 1 and 
    DATEPART(weekday,d) = DATEPART(weekday,'20150913') and --Any known Sunday 
    DATEPART(day,d) between 25 and 31 
) 
select d 
from ApplicableSundays where rn = 2 
option (maxrecursion 0) 

Dates產生於20世紀和21世紀,這是希望爲您的目的足夠靈活,所有日期。

ApplicableSundays過濾掉這些行到@today之前發生的日期,是在一月份,是一個星期天(使用已知良好的日期,而不是依賴於任何特定的DATEFIRST設置)和25日和本月31日下降。

然後,我們選擇這些日期中的第二個最近的日期,如果我們的年份從每個月的最後一個星期日開始,那麼這些日期必須是去年的開始日期。


如果你對一個完整的日期表工作,你希望找到這個「去年開始」值,你會在ApplicableDates CTE介紹它作爲一個join和使用分區ROW_NUMBER()彙總這些值,以便您可以並行查找所有星期日。

+0

偉大,正確和多功能。但是:我的答案的執行計劃=一個節點,「選擇無查詢」。這是一個深度爲13的樹的執行計劃:) – dlatikay

+0

@dlatikay - 是的。我看着你的,我仍然不確定實際的邏輯是什麼。而我的一些複雜來自想要使用日曆表,但另一方面想要提供獨立的腳本。 –