2017-02-22 4 views
0

Я ищу код T-SQL, который должен выбрать дату, которая «Один год назад с текущей даты (в то же время в прошлое воскресенье месяца)».T-SQL date pickup

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

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 выбирал дату в прошлом году (дата последнего воскресенья в январе месяце).

Подробнее - Я хочу, чтобы 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

Если у вас есть таблицы календаря, вы можете пропустить первый КТР (и, возможно, вариант 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-го числа этого месяца ,

Затем мы выбираем вторую самую последнюю из этих дат, которая должна быть в начале прошлого года, если наши годы начинаются в последнее воскресенье каждого января.


Если вы работаете на стол полных дат, на которые вы хотите найти это «начало прошлого года» значение, вы бы ввести его в качестве joinApplicableDates в КТРЕ и разбивает ROW_NUMBER() агрегат с помощью эти ценности, так что вы можете найти все воскресенье параллельно.

+0

отличный, правильный и универсальный. но: план выполнения моего ответа = один узел, «выберите без запроса». план выполнения этого = дерево с глубиной 13 :) – dlatikay

+0

@dlatikay - Да. Я посмотрел на тебя, и я до сих пор не знаю, что такое настоящая логика.И некоторые из моих сложностей связаны с желанием использовать таблицу календаря, но, с другой стороны, хотят предоставить автономный скрипт. –

Смежные вопросы