Eu tenho a seguinte EventTimes
tabela:
DROP TABLE IF EXISTS dbo.EventTimes;
CREATE TABLE dbo.EventTimes
(
EventTimeKeyId INT IDENTITY(1,1) PRIMARY KEY,
EventId INT NOT NULL,
StartTime TIME NOT NULL,
EndTime TIME NOT NULL
);
Com os seguintes dados:
-- Event 1
INSERT INTO dbo.EventTimes (EventId, StartTime, EndTime)
VALUES
(1, '04:00:00', '14:00:00'),
(1, '06:00:00', '11:00:00'),
(1, '09:00:00', '12:00:00'),
(1, '13:00:00', '14:00:00'), -- Gap between this row and the next row
(1, '02:30:00', '04:00:00'); -- Notice the half-hour on this one
-- Event 2
INSERT INTO dbo.EventTimes (EventId, StartTime, EndTime)
VALUES
(2, '00:00:00', '06:00:00'), -- Gap between this row and the next row
(2, '09:00:00', '13:00:00'),
(2, '11:00:00', '15:00:00');
Perceber:
- O mesmo
Event
pode ter dois intervalos de tempo que se sobrepõem. Por exemplo, o mesmoEvent
das 4h às 14h e também das 6h às 11h. - Também pode haver lacunas entre os dois intervalos de tempo. Por exemplo, o mesmo
Event
das 13h às 14h e também das 14h30 às 16h.
Objetivo final:
Estou tentando calcular o valor TotalTime
de um determinado Event
ignorando o tempo de sobreposição duplicado. Por exemplo, para o conjunto de intervalos das 9h00 às 13h00 e das 11h00 às 15h00, o intervalo TotalTime
deverá ser de 6 horas (9h00 às 15h00). Por outro lado, também não quero contar o tempo nos intervalos entre dois intervalos de tempo. Portanto, para o conjunto de intervalos de 13h às 14h e de 14h30 às 16h, TotalTime
deve ser de 2,5 horas. (Observe que estes são apenas subconjuntos do exemplo completo acima, e o resultado final deve ser a soma de todos esses tempos únicos por Event
.)
Nunca TotalTime
deve exceder 24 horas, esses tempos são todos dentro de um único dia (assim como o TIME
tipo de dados).
Resultados finais esperados para os exemplos fornecidos nos scripts acima:
Outras informações:
Se for mais fácil trabalhar com datas e horas, sinta-se à vontade para alterar os tipos de dados de
TIME
paraDATETIME
. Posso converter os resultados de volta, sem problemas.Acredito que algum tipo de recursão seja necessária para resolver isso. Sinto que estou bem perto de uma solução, mas ainda não cheguei lá.
Em um caso como 2h30 - 4h e 4h - 14h, esperaria que o tempo total fosse de 11,5 horas.
Toda a complexidade resulta dos intervalos sobrepostos.
Se compactarmos os intervalos para que não haja sobreposições, a solução será um grupo e uma soma simples.
O código a seguir usa a solução de empacotamento de intervalo de Itzik Ben-Gan :
A classificação inicial pode ser evitada com um índice ativado
(EventId, StartTime, EndTime)
.Aqui está uma solução que usa Run Length Encoding para compactar intervalos de tempo sobrepostos -
ESQUEMA E SAÍDA DESEJADA
SOLUÇÃO
DB Fiddle para referência