Разделите дату на недели от заданной даты до последней даты в записи - PullRequest
0 голосов
/ 03 августа 2020

Я хотел подсчитать временной интервал между двумя строками для одного и того же идентификатора, если второй меньше часа после первого, и разделить счет за неделю.

Предположим, что заданная дата со временем 2020-07-01 08:00

create table #Temp (
  Id integer not null,
  Time datetime not null
);

insert into #Temp  values (1, '2020-07-01 08:00');
insert into #Temp  values (1, '2020-07-01 08:01');
insert into #Temp  values (1, '2020-07-01 08:06');
insert into #Temp  values (1, '2020-07-01 08:30');
insert into #Temp  values (1, '2020-07-08 09:35');
insert into #Temp  values (1, '2020-07-15 16:10');
insert into #Temp  values (1, '2020-07-15 16:20');
insert into #Temp  values (1, '2020-07-17 06:40');
insert into #Temp  values (1, '2020-07-17 06:41');
insert into #Temp  values (2, '2020-07-01 08:30');
insert into #Temp  values (2, '2020-07-01 09:26');
insert into #Temp  values (2, '2020-07-01 10:25');
insert into #Temp  values (2, '2020-07-09 08:30');
insert into #Temp  values (2, '2020-07-09 09:26');
insert into #Temp  values (2, '2020-07-09 10:25');
insert into #Temp  values (3, '2020-07-21 08:30');
insert into #Temp  values (3, '2020-07-21 09:26');
insert into #Temp  values (3, '2020-07-21 10:25');

Неделя должна длиться до последней даты в записи. Здесь последняя дата: 2020-07-21 10:25

Необходимо преобразовать вывод этого фрагмента кода и разделить продолжительность еженедельно.

select Id, sum(datediff(minute, Time, next_ts)) as duration_minutes
from (select t.*,
             lead(Time) over (partition by id order by Time) as next_ts
      from #Temp t
     ) t
where datediff(minute, Time, next_ts) < 60
group by Id;

Вывод:

id  duration_minutes
1   41
2   230
3   115

Желаемый результат должен делить эту продолжительность на еженедельной основе, например Week 1, Week 2, Week 3 и т. Д.

Желаемый результат:

Если начальная дата 2020-07-01 08:00 дата окончания: 2020-07-21 10:25

id  |   Week 1  |   Week 2  |   Week 3
--------------------------------------
1   |   30      |   0       |   11  
2   |   115     |   115     |   0
3   |   0       |   0       |   115

аналогично, если

дата начала 2020-07-08 08:00

id  |   Week 1  |   Week 2  
---------------------------
1   |   11      |   0       
2   |   115     |   0       
3   |   0       |   115     

Ответы [ 2 ]

1 голос
/ 03 августа 2020

Это то, что вы хотите?

select Id,
       1 + datediff(second, '2020-07-01 06:00', time) / (24 * 60 * 60 * 7) as week_num,
       sum(datediff(minute, Time, next_ts)) as duration_minutes
from (select t.*,
             lead(Time) over (partition by id order by Time) as next_ts
      from Temp t
     ) t
where datediff(minute, Time, next_ts) < 60
group by Id, datediff(second, '2020-07-01 06:00', time) / (24 * 60 * 60 * 7)
order by id, week_num;

Здесь - скрипт db <>.

0 голосов
/ 03 августа 2020

Я не могу понять лог c за точками week. Кто угодно, в приведенном ниже примере я использую следующий код для установки week:

'Week ' + CAST(DENSE_RANK() OVER (ORDER BY DATEDIFF(DAY, @FirstDate, next_ts) / 7)  AS VARCHAR(12))

Вы можете настроить его так, чтобы игнорировать наши, точнее или что-то еще, чтобы соответствовать вашим реальным требованиям.

Кроме того, вам просто нужно выполнить динамику c PIVOT. Вот полный рабочий пример:

DROP TABLE IF EXISTS #Temp;

create table #Temp (
  Id integer not null,
  Time datetime not null
);

insert into #Temp  values (1, '2020-07-01 08:00');
insert into #Temp  values (1, '2020-07-01 08:01');
insert into #Temp  values (1, '2020-07-01 08:06');
insert into #Temp  values (1, '2020-07-01 08:30');
insert into #Temp  values (1, '2020-07-08 09:35');
insert into #Temp  values (1, '2020-07-15 16:10');
insert into #Temp  values (1, '2020-07-15 16:20');
insert into #Temp  values (1, '2020-07-17 06:40');
insert into #Temp  values (1, '2020-07-17 06:41');
insert into #Temp  values (2, '2020-07-01 08:30');
insert into #Temp  values (2, '2020-07-01 09:26');
insert into #Temp  values (2, '2020-07-01 10:25');
insert into #Temp  values (2, '2020-07-09 08:30');
insert into #Temp  values (2, '2020-07-09 09:26');
insert into #Temp  values (2, '2020-07-09 10:25');
insert into #Temp  values (3, '2020-07-21 08:30');
insert into #Temp  values (3, '2020-07-21 09:26');
insert into #Temp  values (3, '2020-07-21 10:25');


DROP TABLE IF EXISTS #TEST

CREATE TABLE #TEST
(
   [ID] INT
  ,[week_day] VARCHAR(12)
  ,[time_in_minutes] BIGINT
)

DECLARE @FirstDate DATE;

SELECT  @FirstDate = MIN(Time)
FROM #Temp

INSERT INTO #TEST
select id
      ,'Week ' + CAST(DENSE_RANK() OVER (ORDER BY DATEDIFF(DAY, @FirstDate, next_ts) / 7)  AS VARCHAR(12))
      ,datediff(minute, Time, next_ts) 
from (select t.*,
             lead(Time) over (partition by id order by Time) as next_ts
      from #Temp t
     ) t
where datediff(minute, Time, next_ts) < 60



DECLARE @columns NVARCHAR(MAX);

SELECT @columns = STUFF
(
    (
        SELECT ',' + QUOTENAME([week_day])
        FROM 
        (
            SELECT DISTINCT CAST(REPLACE([week_day], 'Week ', '') AS INT)
                           ,[week_day]
            FROM #TEST
        ) DS ([rowID], [week_day])
        ORDER BY [rowID]
        FOR XML PATH(''), TYPE
    ).value('.', 'VARCHAR(MAX)')
    ,1
    ,1
    ,''
);


DECLARE @DanymicSQL NVARCHAR(MAX);

SET @DanymicSQL = N'
SELECT [ID], ' + @columns + '
FROM #TEST
PIVOT
(
    SUM([time_in_minutes]) FOR [week_day] IN (' + @columns + ')
) PVT';

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