Как узнать, сколько часов 4 утра в день во вторник было между двумя датами в TSQL - PullRequest
0 голосов
/ 18 октября 2019

У меня есть очень конкретная статистика, от которой мне нужно получить информацию.

Это продолжение этого вопроса, который просто задает вопрос о 4 утра, теперь мне нужно добавить, что он былвторник

Как узнать, сколько часов 4 утра было между двумя датами в TSQL

Мне нужно выяснить, сколько вхождений определенного временидня в определенный день недели между двумя датами.

Например, мне нужно узнать, сколько 4 утра во вторник было между двумя датами.

КакНапример, следующее даст результат = 1, так как во вторник 1 вхождение в 4 часа утра

declare @date1 datetime = '2019-10-01 00:00:00.000';
declare @date2 datetime = '2019-10-02 00:00:00.000';

В качестве примера следующее даст результат = 0, так как вВторник

declare @date1 datetime = '2019-10-01 05:00:00.000';
declare @date2 datetime = '2019-10-02 00:00:00.000';

В качестве примера, следующее даст результат = 2, так как было 2 4 AMs

declare @date1 datetime = '2019-10-01 03:00:00.000';
declare @date2 datetime = '2019-10-08 05:00:00.000';

В качестве примера, следующее даст результат = 2 какбыло 2 4 утра, хотя они просто оВ 4:00 утра по вторникам с интервалом

declare @date1 datetime = '2019-10-01 04:00:00.000';
declare @date2 datetime = '2019-10-08 04:00:00.000';

У меня есть какой-то код, чтобы узнать Сколько дней недели между двумя датами и сколько 4 утра между двумя датами, но не вместе.

Вот код, который я пробовал, который работает для 3 из 4 моих тестов.

SET DATEFIRST 1
declare @HourOfDay int = 4

declare @tests table (
    date1 datetime,
    date2 datetime
)

INSERT INTO @tests VALUES
('2019-10-01 00:00:00.000', '2019-10-02 00:00:00.000'), -- returns 1 CORRECT
('2019-10-01 05:00:00.000', '2019-10-02 00:00:00.000'), -- returns 1 INCORRECT
('2019-10-01 03:00:00.000', '2019-10-08 05:00:00.000'), -- returns 2 CORRECT
('2019-10-01 04:00:00.000', '2019-10-08 04:00:00.000'); -- returns 2 CORRECT

select
date1,
date2,
DATEDIFF(DAY,DATEADD(SECOND,-1,DATEADD(HOUR, -1 * @HourOfDay, date1)),DATEADD(HOUR, -1 * @HourOfDay, date2)) / 7 + 1
from @tests

Ответы [ 3 ]

2 голосов
/ 18 октября 2019

Я бы предложил таблицу календаря, но вы также можете использовать специальную таблицу подсчета / чисел

В подзапросе B мы создаем таблицу календаря на лету с 10 000 дней, начиная с2015-12-31. Вы можете настроить или сделать динамическим

Пример

Declare @YourTable table (Date1 datetime,Date2 datetime)
Insert Into @YourTable values
 ('2019-10-01 00:00:00.000','2019-10-02 00:00:00.000')
,('2019-10-01 05:00:00.000','2019-10-02 00:00:00.000')
,('2019-10-01 03:00:00.000','2019-10-08 05:00:00.000')
,('2019-10-01 04:00:00.000','2019-10-08 04:00:00.000')



Select A.*
      ,Cnt=count(D)
 From  @YourTable A
 Left Join  (
        Select D = DateAdd(DAY,N,'2015-12-31 04:00:00')
         From ( Select Top 10000 N=Row_Number() Over (Order By (Select NULL)) From master..spt_values n1, master..spt_values n2 ) A
       ) B
 On DateName(WEEKDAY,D)='Tuesday'
   and D >=Date1 and D<=Date2
 Group By Date1,Date2

Возвращает

Date1                    Date2                      Cnt
2019-10-01 00:00:00.000  2019-10-02 00:00:00.000    1
2019-10-01 05:00:00.000  2019-10-02 00:00:00.000    0
2019-10-01 04:00:00.000  2019-10-08 04:00:00.000    2
2019-10-01 03:00:00.000  2019-10-08 05:00:00.000    2
1 голос
/ 18 октября 2019

Попробуйте это:

SET DATEFIRST 1
declare @HourOfDay int = 4
declare @weekday int=2
declare @tests table (
    date1 datetime,
    date2 datetime
)


INSERT INTO @tests VALUES
('2019-10-01 00:00:00.000', '2019-10-02 00:00:00.000'), 
('2019-10-01 05:00:00.000', '2019-10-02 00:00:00.000'), 
('2019-10-01 03:00:00.000', '2019-10-08 05:00:00.000'), 
('2019-10-01 04:00:00.000', '2019-10-08 04:00:00.000'),
('2019-10-03 04:00:00.000', '2019-10-11 02:00:00.000'),
('2019-10-03 04:00:00.000', '2019-10-15 04:00:00.000'),
('2019-10-03 04:00:00.000', '2019-10-15 02:00:00.000'); 

;WITH cte(date1,date2,dt1,dt2)
AS
(
select
date1,
date2,
CASE WHEN datepart(weekday,date1)=@weekday AND datepart(hour,date1)<=@HourOfDay THEN 1 ELSE 0 END,  
CASE WHEN datepart(weekday,date2)=@weekday AND datepart(hour,date2)>=@HourOfDay THEN 1 ELSE 0 END
FROM @tests
)
select
date1,
date2,
dt1+dt2+DATEDIFF(DAY,DATEADD(DAY,dt1,date1),DATEADD(DAY,0-dt2,date2))/7
from cte
1 голос
/ 18 октября 2019

Я нашел решение, которое, кажется, работает для моих тестовых случаев ... Мне все же нужно провести еще какое-то тестирование.

Мне было бы интересно услышать, если кто-то думает, что моя логика неверна

SET DATEFIRST 1
declare @HourOfDay int = 4
declare @DayOfWeek int = 2

declare @tests table (
    date1 datetime,
    date2 datetime
)

INSERT INTO @tests VALUES
('2019-10-01 00:00:00.000', '2019-10-02 00:00:00.000'), -- returns 1 CORRECT
('2019-10-01 05:00:00.000', '2019-10-02 00:00:00.000'), -- returns 1 INCORRECT
('2019-10-01 03:00:00.000', '2019-10-08 05:00:00.000'), -- returns 2 CORRECT
('2019-10-01 04:00:00.000', '2019-10-08 04:00:00.000'); -- returns 2 CORRECT

select
date1,
date2,
DATEDIFF(DAY,DATEADD(SECOND,-1,DATEADD(HOUR, -1 * @HourOfDay, date1)),DATEADD(HOUR, -1 * @HourOfDay, date2)) / 7 + 1
+ CASE 
    WHEN (DATEPART(DW, date1) = @DayOfWeek AND DATEPART(HOUR, date1) <= @HourOfDay AND
    DATEPART(HOUR, date2) <= @HourOfDay) OR 
    (DATEPART(DW, date2) = @DayOfWeek AND DATEPART(HOUR, date2) >= @HourOfDay AND
    DATEPART(HOUR, date1) <= @HourOfDay)
THEN 0
ELSE -1 END

from @tests
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...