自动提取日期来自SQL Server

时间:2017-02-21 17:04:27

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

我正在寻找一些T-SQL代码,它应该选择一月份的最后一个星期日"

例如:

Current day      expected result
2017-01-29       2016-01-31
2017-02-05       2017-01-29
2017-02-19       2017-01-29
2018-01-28       2017-01-29
2018-02-04       2018-01-28

这是因为这一年从一月的最后一个星期日开始

我有一些在SQL Server 2014中使用的T-SQL代码:

select 
    convert(varchar(10), DATEADD(day, DATEDIFF(day, '19000107', DATEADD(month, DATEDIFF(MONTH, 0, CONVERT(date, CONVERT(VARCHAR(4), GETDATE(), 112) + '0101')), 30)) / 7  * 7, '19000107'), 120)

如果当前日期是2月到12月之间,那么上面的代码会返回正确的答案。但是,如果我们将当前日期设置为' 2017-01-25' (或1月份的任何其他日期),结果是错误的。

对于上述日期(2017-01-25),答案应为' 2016-01-31'

3 个答案:

答案 0 :(得分:2)

问题可能是查询找到了所提供年份的Jan的第一天,但​​如果Jan是提供的月份,则会有所不同。 更改是确定Jan是否是提供的月份,并将去年作为年份返回。

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)

CASE中的CONVERT(date, CONVERT(VARCHAR(4)语句是进行更改的地方。

答案 1 :(得分:0)

查找表是解决此类问题的最佳方法

WITH lookup(d) AS
(
  VALUES( ('2016-01-31'),
          ('2017-01-29'),
          ('2018-01-28')
)
select MAX(d)
FROM lookup
WHERE d <= GETDATE()

答案 2 :(得分:0)

最右边一列将计算任何日期1月份的上一个星期日。我已经将其他列留下来作为记录和试验逻辑的简单方法。

没有分支逻辑,它都是纯日期数学,所以它应该合理地快速聚合,并且应该能够在日期列上使用索引。

DECLARE @Date DATE = '20170205';
SELECT SampleDate= @Date  ,
    PreviousLastSundayInJanuaryForSampleDate = DATEADD(DAY,(DATEPART(WEEKDAY,EOMONTH(DATEADD(MONTH,(DATEPART(MONTH
,DATEADD(DAY,((DATEPART(DAYOFYEAR,DATEADD(DAY,(DATEPART(WEEKDAY,EOMONTH(DATEADD(MONTH,(DATEPART(MONTH,@Date)-1)*-1,@Date)))-1)*-1,EOMONTH(DATEADD(MONTH,(DATEPART(MONTH,@Date)-1)*-1,@Date)))))-1) * -1 ,@Date))-1)*-1
,DATEADD(DAY,((DATEPART(DAYOFYEAR,DATEADD(DAY,(DATEPART(WEEKDAY,EOMONTH(DATEADD(MONTH,(DATEPART(MONTH,@Date)-1)*-1,@Date)))-1)*-1,EOMONTH(DATEADD(MONTH,(DATEPART(MONTH,@Date)-1)*-1,@Date)))))-1) * -1 ,@Date))))-1)*-1,EOMONTH(DATEADD(MONTH,(DATEPART(MONTH
,DATEADD(DAY,((DATEPART(DAYOFYEAR,DATEADD(DAY,(DATEPART(WEEKDAY,EOMONTH(DATEADD(MONTH,(DATEPART(MONTH,@Date)-1)*-1,@Date)))-1)*-1,EOMONTH(DATEADD(MONTH,(DATEPART(MONTH,@Date)-1)*-1,@Date)))))-1) * -1 ,@Date))-1)*-1
,DATEADD(DAY,((DATEPART(DAYOFYEAR,DATEADD(DAY,(DATEPART(WEEKDAY,EOMONTH(DATEADD(MONTH,(DATEPART(MONTH,@Date)-1)*-1,@Date)))-1)*-1,EOMONTH(DATEADD(MONTH,(DATEPART(MONTH,@Date)-1)*-1,@Date)))))-1) * -1 ,@Date)))) 

要对表使用此功能,请将@Date替换为您自己的日期字段。

更新了样本结果:

SampleDate  PreviousLastSundayInJanuaryForSampleDate
2008-06-03  2008-01-27
2008-12-20  2008-01-27
2009-07-08  2009-01-25
2010-01-24  2009-01-25
2010-08-12  2010-01-31
2011-02-28  2011-01-30
2011-09-16  2011-01-30
2012-04-03  2012-01-29
2012-10-20  2012-01-29
2013-05-08  2013-01-27
2013-11-24  2013-01-27
2014-06-12  2014-01-26
2014-12-29  2014-01-26
2015-07-17  2015-01-25
2016-02-02  2016-01-31
2016-08-20  2016-01-31
2017-03-08  2017-01-29
2017-09-24  2017-01-29
2018-04-12  2018-01-28
2018-10-29  2018-01-28
2019-05-17  2019-01-27
2019-12-03  2019-01-27
2020-06-20  2020-01-26