SQL «округляет» дату до заданного дня недели - PullRequest
1 голос
/ 20 марта 2019

Моя компания группирует все задачи в отдельные недели, которые заканчиваются в четверг.Таким образом, задание на 3/20/19 будет сгруппировано в неделю 3/21, а задание на 3/22 - на неделю 3/28/19.

Я рассчитываю рассчитать это поле(называемый duedate_Weekdue), основанный на вводе duedate.

Следующее работает, но не кажется самым простым способом сделать это.У кого-нибудь есть более изящные методы?

Select 
getdate() as duedate,
datepart(yy,getdate()) as duedate_yr,
datepart(ww,getdate()) as duedate_ww,
CASE
    When datename(dw,Dateadd(day,1,getdate()))='Thursday' Then Dateadd(day,1,getdate())
    When datename(dw,Dateadd(day,2,getdate()))='Thursday' Then Dateadd(day,2,getdate())
    When datename(dw,Dateadd(day,3,getdate()))='Thursday' Then Dateadd(day,3,getdate())
    When datename(dw,Dateadd(day,4,getdate()))='Thursday' Then Dateadd(day,4,getdate())
    When datename(dw,Dateadd(day,5,getdate()))='Thursday' Then Dateadd(day,5,getdate())
    When datename(dw,Dateadd(day,6,getdate()))='Thursday' Then Dateadd(day,6,getdate())
    When datename(dw,Dateadd(day,0,getdate()))='Thursday' Then Dateadd(day,0,getdate())
END as duedate_Weekdue;

Ответы [ 3 ]

1 голос
/ 20 марта 2019

Вы можете уменьшить это до одной строки кода, которая использует немного математики и некоторые мелочи SQL Engine.

Ответы, которые зависят от DATEPART, возвращают недетерминированные результаты в зависимости от настройки для DATEFIRST, который сообщает SQL Engine, какой день недели считать первым днем ​​недели.

Существует способ сделать то, что вы хотите, без риска ошибитьсярезультат, основанный на изменении параметра DATEFIRST.

Внутри SQL Server днем ​​0 является 1 января 1900 года, что является понедельником.Мы все использовали этот маленький трюк, чтобы убрать время из GETDATE(), подсчитав количество дней с 0 дня, а затем добавив это число к 0, чтобы получить сегодняшнюю дату в полночь:

SELECT DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()),0)

АналогичноДень 3 был 4 января 1900 года. Это важно, потому что этот день был четверг.Приложив немного математики к числу дней и полагаясь на функцию DATEDIFF, чтобы отбрасывать дроби, что и делает, этот расчет всегда вернет вам следующий четверг:

SELECT DATEADD(DAY, (DATEDIFF(DAY, 3, GETDATE())/7)*7 + 7,3);

Закажите этот ответ за помощь.

Итак, ваш последний запрос сводится к следующему:

Select 
getdate() as duedate,
datepart(yy,getdate()) as duedate_yr,
datepart(ww,getdate()) as duedate_ww,
DATEADD(DAY, (DATEDIFF(DAY, 3, GETDATE())/7)*7 + 7,3) as duedate_Weekdue;
0 голосов
/ 20 марта 2019

Если первый день недели - воскресенье, с помощью оператора по модулю %:

cast(dateadd(day, (13 - datepart(dw, getdate())) % 7, getdate()) as date)  as duedate_Weekdue

я также применил приведение результата к date.

0 голосов
/ 20 марта 2019

Попробуйте указать число дней в неделе с помощью DATEPART, а затем добавьте достаточно дней, чтобы перейти к следующему четвергу:

declare @dt date = '2019-03-22'
declare @weekDay int

SELECT @weekDay =  DATEPART(dw, @dt)  

if @weekDay <= 5 
    select DATEADD(day, 5 - @weekDay ,@dt)
else
    select DATEADD(day,  12 - @weekDay  ,@dt)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...