CREATE TABLE T1
(Asset_Id int, Trailer_Id int, AssignStart datetime, AssignEnd DATETIME)
;
INSERT INTO T1
(Asset_Id, Trailer_Id, AssignStart, AssignEnd)
VALUES
(37124, 32607, '2018-04-19 08:55:00', '2018-05-05 10:00:00.000'),
(37124, 32607, '2018-05-05 11:23:00', NULL),
(33000, 30000, '2018-04-01 15:00:00', '2018-04-15 10:30:00.000'),
(34000, 31000, '2018-04-05 10:00:00', '2018-04-10 09:30:00.000'),
(34000, 32500, '2018-04-10 09:31:00', NULL),
(37000, 32600, '2018-04-19 08:55:00', '2018-04-25 08:30:00.000'),
(37000, 32600, '2018-04-25 09:23:00', '2018-04-25 10:00:00.000'),
(37000, 32600, '2018-04-25 11:23:00', '2018-04-30 15:00:00.000'),
(37000, 32600, '2018-04-30 16:15:00', '2018-04-30 17:30:00.000'),
(37000, 32600, '2018-05-01 18:23:00', NULL),
(38000, 36000, '2018-05-01 10:00:00', '2018-05-10 06:30:00.000'),
(38000, 36000, '2018-05-15 09:00:00', '2018-05-20 11:00:00.000'),
(38000, 36000, '2018-05-20 12:00:00', NULL),
(33000, 30000, '2018-05-01 10:00:00', NULL)
;
Eu tenho os seguintes dados de exemplo -
Asset_Id Trailer_Id AssignStart AssignEnd
37124 32607 2018-04-19 08:55:00.000 2018-05-05 10:00:00.000
37124 32607 2018-05-05 11:23:00.000 NULL
33000 30000 2018-04-01 15:00:00.000 2018-04-15 10:30:00.000
34000 31000 2018-04-05 10:00:00.000 2018-04-10 09:30:00.000
34000 32500 2018-04-10 09:31:00.000 NULL
37000 32600 2018-04-19 08:55:00.000 2018-04-25 08:30:00.000
37000 32600 2018-04-25 09:23:00.000 2018-04-25 10:00:00.000
37000 32600 2018-04-25 11:23:00.000 2018-04-30 15:00:00.000
37000 32600 2018-04-30 16:15:00 2018-04-30 17:30:00.000
37000 32600 2018-05-01 18:23:00 NULL
38000 36000 2018-05-01 10:00:00.000 2018-05-10 06:30:00.000
38000 36000 2018-05-15 09:00:00.000 2018-05-20 11:00:00.000
38000 36000 2018-05-20 12:00:00.000 NULL
33000 30000 2018-05-01 10:00:00.000 NULL
Como você pode ver, algumas das atribuições entre Ativos e Trailers são encerradas e iniciadas novamente no mesmo dia - exceto a última linha - Gaps e Islands
Exemplo 1)
Asset_Id Trailer_Id AssignStart AssignEnd
37000 32600 2018-04-19 08:55:00.000 2018-04-25 08:30:00.000
37000 32600 2018-04-25 09:23:00.000 2018-04-25 10:00:00.000
37000 32600 2018-04-25 11:23:00.000 2018-04-30 15:00:00.000
37000 32600 2018-04-30 16:15:00.000 2018-04-30 17:30:00.000
37000 32600 2018-05-01 18:23:00.000 NULL
A saída para esta amostra que estou esperando é
Asset_Id Trailer_Id AssignStart AssignEnd
37000 32600 2018-04-19 08:55:00.000 2018-04-30 17:30:00.000
37000 32600 2018-05-01 18:23:00.000 NULL
Agora esta é outra seção com as lacunas e ilhas. Algumas das atribuições entre os mesmos ativos e trailers são encerradas e iniciadas novamente em uma data futura
Exemplo (2)
Asset_Id Trailer_Id AssignStart AssignEnd
33000 30000 2018-04-01 15:00:00.000 2018-04-15 10:30:00.000
33000 30000 2018-05-01 10:00:00.000 NULL
A saída para esta amostra que estou esperando é
Asset_Id Trailer_Id AssignStart AssignEnd
33000 30000 2018-04-01 15:00:00.000 2018-04-15 10:30:00.000
33000 30000 2018-05-01 10:00:00.000 NULL
Exemplo (3)
Asset_Id Trailer_Id AssignStart AssignEnd
38000 36000 2018-05-01 10:00:00.000 2018-05-10 06:30:00.000
38000 36000 2018-05-15 09:00:00.000 2018-05-20 11:00:00.000
38000 36000 2018-05-20 12:00:00.000 NULL
A saída para esta amostra que estou esperando é
Asset_Id Trailer_Id AssignStart AssignEnd
38000 36000 2018-05-01 10:00:00.000 2018-05-10 06:30:00.000
38000 36000 2018-05-15 09:00:00.000 NULL
Estou lutando para escrever uma consulta que fornecerá a seguinte saída
Asset_Id Trailer_Id AssignStart AssignEnd
37124 32607 2018-04-19 08:55:00.000 NULL
33000 30000 2018-04-01 15:00:00.000 2018-04-15 10:30:00.000
34000 31000 2018-04-05 10:00:00.000 2018-04-10 09:30:00.000
34000 32500 2018-04-10 09:31:00.000 NULL
37000 32600 2018-04-19 08:55:00.000 2018-04-30 17:30:00.000
37000 32600 2018-05-01 18:23:00.000 NULL
38000 36000 2018-05-01 10:00:00.000 2018-05-10 06:30:00.000
38000 36000 2018-05-15 09:00:00.000 NULL
33000 30000 2018-05-01 10:00:00.000 NULL
Usando a resposta desta resposta SO como base, esta é minha tentativa , não está certo
Você pode usar a abordagem recursiva, com a ajuda de um CTE. Para isso, adicionei um
Row_Number
so , para ter certeza de que é o próximo registro verificado.Em seguida, criando o CTE recursivo... chamado
cte
. Aqui é importante o camporn as rn_init
- esta é a base na hora de criar a cadeia de registros.Aqui está lidando com
NULL
case para o AssignEnd e também importante, para contar a 'cadeia de registros'count(rn_init) as c_rn_init
. Com base nisso, é posteriormente filtrado.Isso se a consulta final. Adicionado Row_number , para filtrar registros,
ORDER BY c_rn_init DESC
A saída:
dbfiddle
Minha ideia é pegar o valor AssignStart, do próximo registro e fazer uma diferença de dia entre [AssignEnd] (da linha atual) e AssignStart (da próxima linha) (Step1)
se for sql server 2012, podemos usar LEAD
se for 2008, não podemos usar LEAD , então use OUTER APPLY para obter o registro:
isso vai me dar o
AssignStart
da próxima linha, com base em[Asset_Id], [Trailer_Id]
Step2: faça essa coluna de diferença:
DATEDIFF(DAY,[AssignEnd],next_AssignStart)
Passo 3: faça um agrupamento nesta coluna, do passo 2
resultado:
ps: adicionado Order by, para que eu possa verificar muito mais facilmente.
ps2: porque ,
NULL
é ignorado no MAX, usei essa expressão para lidar com a parte superior do intervalodbfiddle
Apresento minha solução para T-SQL.
Fiddle SQL Server 2017
O problema:
Precisamos empacotar registros por intervalo de datas sobrepostos (unidade de tempo base 'dia') particionados por Ativo e Trailer.
A solução:
O empacotamento de intervalos de datas sobrepostos requer 3 etapas:
Etapa 1 : determinar um GroupStart
Etapa 2 : determinar os grupos
Etapa 3 : determinar o intervalo de datas compactado
Configurar:
Consulta completa:
Você pode tentar a auto-junção como alternativa.
No meu ambiente (com os dados de exemplo) está gerando menos leituras que o OUTER APPLY. e produzir um plano de execução menos dispendioso. Mas quando eu adiciono índices diferentes, o OUTER APPLY às vezes sai no topo.