2017-02-21 22 views
-1

Я ищу код T-SQL, который должен выбрать дату, которая является «последним воскресеньем в январе».Даты автопилота с SQL Server

Например:

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 

Это происходит потому, что год начинается с последнего воскресенья в январе

У меня есть T-SQL-код, который используется в SQL Server 2014:

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) 

Если текущая дата находится между февралем и декабрем, то приведенный выше код возвращает правильный ответ. Но если мы установим текущую дату как «2017-01-25» (или любые другие даты в январе), результат будет неправильным.

Для указанной даты (2017-01-25) ответа должен быть «2016-01-31»

+0

Либо DatePart или datename функция поможет вам в этом. –

+0

@ dan-bracuk Могли бы вы обновить код T-SQL и отправить их? Это будет очень полезно. – user2331670

ответ

2

проблема может заключаться в том, что запрос находит первый день января в течение года, но это будет отличаться, если 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) ... где было сделано изменение.

+0

спасибо, работал. Мне нужен еще один код T-SQL для другого сценария. Сценарий «Для той же концепции я хочу, чтобы код T-SQL выбирал дату предыдущего года». Например 1. Текущая дата - «2017-02-21», затем код должен выбрать «2016-01-31». Например 2. Текущая дата - «2018-02-21», тогда код должен выбрать «2017-01-29». Любая помощь пожалуйста. – user2331670

0

таблицы поиска является лучшим способом для решения такого рода проблем

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

Самый правый столбец этого будет вычислять предыдущее последнее воскресенье января для любой даты. Я оставил остальные столбцы как простой способ документировать и экспериментировать с логикой.

Существует не логика ветвления, это чистая математика, поэтому она должна быть достаточно быстрой и должна иметь возможность использовать индексы в столбце даты.

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