T-SQL日期提取

时间:2017-02-22 09:46:28

标签: sql sql-server sql-server-2008 date sql-server-2012

我正在寻找一些T-SQL代码,它应该选择的日期是"从当前日期开始的一年(在1月份的最后一个星期日的同一时间)"。

我有一些在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)

以上代码选择当前年份的日期(1月份的最后一个星期日)。但我希望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

请注意,年份始于" 1月份的最后一个星期日"。

3 个答案:

答案 0 :(得分: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)

答案 1 :(得分: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之前的日期,即1月份,是星期日(使用已知良好的日期,而不是依赖于任何特定的DATEFIRST设置)并且在那个月的25日和31日之间。

如果我们的年份从每年一月的最后一个星期日开始,那么我们选择这些日期中的第二个日期,这必须是去年的开始。

如果你正在反对一个满桌的日程表,你希望找到这个日期,并且去年开始#34;值,您可以在join CTE中将其作为ApplicableDates引入,并使用这些值对ROW_NUMBER()聚合进行分区,以便您可以并行查找所有星期日。

答案 2 :(得分: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