#sql #sql-server #tsql
#sql #sql-сервер #tsql
Вопрос:
Как добавить в следующий скрипт дополнительный подсчет времени только в часы 10:00 <> 18:00. Если время @StartDate
— 09:00, то мы рассматриваем его как 10:00
Пример:
SET @StartDate = '2021/12/10 09:00:00'
SET @EndDate = '2021/12/11 18:30:00'
Ожидаемый результат по минутам — это сумма минут с 10:00 до 18:00, так что 8 * 60 = 480 минут.
Спасибо за советы
DECLARE @StartDate DATETIME
DECLARE @EndDate DATETIME
SET @StartDate = '2013/03/15 23:30:00'
SET @EndDate = '2013/03/17 00:30:00'
SELECT
( DATEDIFF(MINUTE, @StartDate, @EndDate)
- ( DATEDIFF(wk, @StartDate,@EndDate)*(2*24*60)
-- End on Sunday
-(CASE WHEN DATEPART(dw, @EndDate) = 1 THEN 24.0*60-DATEDIFF(minute,CONVERT(date,@EndDate),@EndDate) ELSE 0 END)
-- Start on Saturday
-(CASE WHEN DATEPART(dw, @StartDate) = 7 THEN DATEDIFF(minute,CONVERT(date,@StartDate),@StartDate) ELSE 0 END)
-- End on Saturday
(CASE WHEN DATEPART(dw, @EndDate) = 7 THEN DATEDIFF(minute,CONVERT(date,@EndDate),@EndDate) ELSE 0 END)
-- Start on Saturday
(CASE WHEN DATEPART(dw, @StartDate) = 1 THEN 24.0*60-DATEDIFF(minute,CONVERT(date,@StartDate),@StartDate) ELSE 0 END)
)
)
Комментарии:
1. В этом случае таблица календаря или подсчет были бы наиболее полезны.
2. Есть решение? Приведенное выше работает нормально, но перечисление в контексте временного интервала отсутствует, и мне интересно, как его использовать, потому что запрос почти готов 🙂
Ответ №1:
Попробуйте это.
DECLARE @StartDate DATETIME
DECLARE @EndDate DATETIME
DECLARE @MinDateTime DATETIME
DECLARE @MaxDateTime DATETIME
SET @StartDate = '2021/12/10 09:00:00'
SET @EndDate = '2021/12/10 18:30:00'
SET @MinDateTime = CONVERT(datetime, CONCAT(CONVERT(DATE, @StartDate), ' 10:00:00'))
SET @MaxDateTime = CONVERT(datetime, CONCAT(CONVERT(DATE, @EndDate), ' 18:00:00'))
SELECT
( DATEDIFF(MINUTE, @StartDate, @EndDate)
- ( DATEDIFF(wk, @StartDate,@EndDate)*(2*24*60)
-- End on Sunday
-(CASE WHEN DATEPART(dw, @EndDate) = 1 THEN 24.0*60-DATEDIFF(minute,CONVERT(date,@EndDate),@EndDate) ELSE 0 END)
-- Start on Saturday
-(CASE WHEN DATEPART(dw, @StartDate) = 7 THEN DATEDIFF(minute,CONVERT(date,@StartDate),@StartDate) ELSE 0 END)
-- End on Saturday
(CASE WHEN DATEPART(dw, @EndDate) = 7 THEN DATEDIFF(minute,CONVERT(date,@EndDate),@EndDate) ELSE 0 END)
-- Start on Saturday
(CASE WHEN DATEPART(dw, @StartDate) = 1 THEN 24.0*60-DATEDIFF(minute,CONVERT(date,@StartDate),@StartDate) ELSE 0 END)
)
),
DATEDIFF(minute, CASE WHEN @StartDate < @MinDateTime
THEN @MinDateTime
ELSE @StartDate
END,
CASE WHEN @EndDate > @MaxDateTime
THEN @MaxDateTime
ELSE @EndDate
END) AS diff
Протестируйте это демо
Комментарии:
1. Хороший ответ содержит объяснение, в дополнение к наличию рабочего кода, так что OP извлекает из него уроки.
Ответ №2:
Просто еще один вариант (перебор).
Может занимать несколько дней. Может быть расширен, чтобы включить праздники.
Declare @Date1 datetime = '2021/12/10 10:00:00'
Declare @Date2 datetime = '2021/12/12 18:30:00'
Select Minutes = count(*)
From ( Select Top (DateDiff(Minute,@Date1,@Date2) 1) D=DateAdd(MINUTE,-1 Row_Number() Over (Order By (Select Null)),@Date1)
From master..spt_values n1,master..spt_values n2
) A
Where datepart(WEEKDAY,D) not in (1,7)
and convert(time,D) >= '10:00'
and convert(time,D) < '18:00'
and convert(date,D) not in ('2021-12-25','2022-01-01') -- Holidays: Should be a table
Результаты
Minutes
480
Комментарии:
1. В сторону:
( @@DateFirst DatePart( weekday, SampleDate ) - 1 ) % 7 1
всегда возвращает целое число от1
до7
с1
, соответствующее воскресенью, независимо от установкиDateFirst
илиLanguage
.2. @HABO Достаточно справедливо. На самом деле я предпочитаю использовать DATENAME(ДЕНЬ НЕДЕЛИ, …), но я заметил, что OP использовал 1 и 7