DATEPART: указание первого дня недели, когда SET DATEFIRST не может быть использован - PullRequest
0 голосов
/ 30 сентября 2019

Я создаю несколько отчетов в ReportServer (тип динамического списка), один из которых извлекает информацию из SQL Server для событий за последнюю неделю.

В SSMS все достаточно просто, я получаю необходимую информацию(по времени) с

... WHERE DATEPART(week, event_date) = DATEPART(week, DATEADD(d, -5, GETDATE()))

, перед которым стоит оператор

SET DATEFIRST 1;

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

К сожалению, ReportServer непримите оператор SET DATEFIRST как часть запроса, поэтому после его пропуска возвращаемые данные колеблются с воскресенья по субботу, а не с понедельника по воскресенье. Я не могу внести глобальные изменения в базу данных (или сервер, если на то пошло).

Как я могу обойти это?

Ответы [ 3 ]

2 голосов
/ 30 сентября 2019

Рассчитайте желаемый первый день недели, а затем используйте диапазон дат недели в вашем предложении where, например,

declare @FirstDayOfWeek date, @Now date = getdate();

select @FirstDayOfWeek = dateadd(day, -1*(case when datepart(weekday, @Now) > 1 then datepart(weekday, @Now)-2 else 6 end), @Now);

select *
from dbo.MyTable
where event_date >= @FirstDayOfWeek and event_date < dateadd(week, 1, @FirstDayOfWeek);

И, конечно, вы также можете встроить вычисление в запрос, например,

select *
from dbo.MyTable
cross join (
  select dateadd(day, -1*(case when datepart(weekday, getdate()) > 1 then datepart(weekday, getdate())-2 else 6 end), getdate()) FirstDayOfWeek
) D
where event_date >= D.FirstDayOfWeek and event_date < dateadd(week, 1, D.FirstDayOfWeek);

Примечание. Вы можете просто дублировать вычисление даты в предложении where и избегать join, но мне не нравится дублировать вычисления.

0 голосов
/ 30 сентября 2019

Поскольку вы хотели, чтобы неделя начиналась с Monday, вы используете контрольную дату, равную Monday, например 1900-01-01, и рассчитывает дату начала и окончания недели

begin_of_week = dateadd(day, datediff(day, '1900-01-01', [date]) / 7 * 7, '1900-01-01')

и получитедата конца недели,

end_of_week = dateadd(day, datediff(day, '1900-01-01', [date]) / 7 * 7 + 7, '1989-12-31')

, поэтому укажите это в своем запросе (я предполагаю, что ваша event_date может содержать компонент времени, поэтому верхнее условие - less than <)

WHERE event_date >= dateadd(day, datediff(day, '1900-01-01', getdate()) / 7 * 7, '1900-01-01')
AND   event_date <  dateadd(day, datediff(day, '1900-01-01', getdate()) / 7 * 7 + 7, '1900-01-01')
0 голосов
/ 30 сентября 2019

Вы можете попробовать что-то подобное, используя @@DATEFIRST. Это системная переменная, которую вы можете использовать без какого-либо объявления или установки во встроенных / специальных запросах:

- это воскресенье

DECLARE @OneSunday DATE='20190929';

- ваше утверждение возвращается по-разному в разныхкультур

SET LANGUAGE ENGLISH;
SELECT DATEPART(week, @OneSunday); --<-- returns 40
SELECT @@DATEFIRST;                --<-- returns 7  

SET LANGUAGE GERMAN;
SELECT DATEPART(week, @OneSunday); --<-- returns 39
SELECT @@DATEFIRST;                --<-- returns 1

Как видите, системная переменная @@DATEFIRST отражает индекс дня, который устанавливается культурой. И вы можете использовать его для коррекционной арифметики.

SET LANGUAGE ENGLISH;
SELECT DATEPART(week, DATEADD(DAY,(@@DATEFIRST % 7),@OneSunday));

SET LANGUAGE GERMAN;
SELECT DATEPART(week, DATEADD(DAY,(@@DATEFIRST % 7),@OneSunday));

Теперь оба возвращают 40.

Я использую % 7, чтобы получить 0, где @@DATEFIRST возвращает 7.

...