2017-02-22 69 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 - 是的。我看着你的,我仍然不确定实际的逻辑是什么。而我的一些复杂来自想要使用日历表,但另一方面想要提供独立的脚本。 –