Tabla de contenido
0 necesidades
Dados varios períodos de tiempo, cada período de tiempo se divide en hora de inicio y hora de finalización, y varios períodos de tiempo superpuestos se fusionan en un solo intervalo
--数据:id、开始时间、结束时间
1 12 15
2 57 58
3 29 32
4 30 31
5 17 19
6 44 44
7 56 57
8 16 18
El resultado combinado es el siguiente;
--结果
flag start_time end_time
1 12 15
2 16 19
3 29 32
4 44 44
5 56 58
1 Preparación de datos
create table test02 as
select 1 as id, 12 as start_time, 15 as end_time
union all
select 2 as id, 57 as start_time, 58 as end_time
union all
select 3 as id, 29 as start_time, 32 as end_time
union all
select 4 as id, 30 as start_time, 31 as end_time
union all
select 5 as id, 17 as start_time, 19 as end_time
union all
select 6 as id, 44 as start_time, 44 as end_time
union all
select 7 as id, 56 as start_time, 57 as end_time
union all
select 8 as id, 16 as start_time, 18 as end_time
2 Análisis de datos
Puntos de resolución de problemas: ¿Cómo juzgar qué intervalos se van a fusionar?
De hecho, desde otra perspectiva, ¿qué intervalos se cortan y cuáles se repiten?
Idea de juicio: si la hora de inicio y la hora de finalización están ordenadas, y la hora de inicio de la fila actual es menor o igual que la hora de finalización de la fila anterior, entonces las fechas se superponen y existen datos duplicados. De acuerdo con esta condición, podemos establecer un punto de interrupción y luego usar la idea clásica de sum() over() para obtener la identificación del grupo, y el problema se resolverá.
Paso 1: ordene en orden descendente según la hora de inicio y la hora de finalización, y obtenga la hora de finalización de la fila anterior para comparar
select id,
start_time,
end_time,
lag(end_time, 1, end_time) over (order by start_time asc, end_time asc) as lga_end_time
from test02
Paso 2: a juzgar según lag_end_time, cuando start_time de la fila actual <= lag_end_time, establezca el valor de la marca en 0; de lo contrario, es 1 (la idea de agrupación clásica después de cambiar las condiciones, aquí debe establecerse en 0 cuando se cumplen las condiciones , y no satisfecho Establecer en 1 cuando condición)
select id
, start_time
, end_time
, case when start_time <= lga_end_time then 0 else 1 end as flg --条件成立的时候为0,不成立的时候为1
from (select id,
start_time,
end_time,
lag(end_time, 1, end_time) over (order by start_time asc, end_time asc) as lga_end_time
from test02
Paso 3: obtenga la identificación del grupo de acuerdo con el método de sum() over()
select id
, start_time
, end_time
, sum(flg) over (order by start_time, end_time ) as grp_id
from (select id
, start_time
, end_time
, case when start_time <= lga_end_time then 0 else 1 end as flg --条件成立的时候为0,不成立的时候为1
from (select id,
start_time,
end_time,
lag(end_time, 1, end_time) over (order by start_time asc, end_time asc) as lga_end_time
from test02
) t
) t
Paso 4: obtenga los valores mínimo y máximo en el grupo, el valor mínimo es el punto de inicio, el valor máximo es el punto final y la identificación del grupo es la identificación
El SQL final es el siguiente:
select grp_id + 1 as id
, min(start_time) as start_time
, max(end_time) as end_time
from (
select id
, start_time
, end_time
, sum(flg) over (order by start_time, end_time ) as grp_id
from (select id
, start_time
, end_time
, case when start_time <= lga_end_time then 0 else 1 end as flg --条件成立的时候为0,不成立的时候为1
from (select id,
start_time,
end_time,
lag(end_time, 1, end_time) over (order by start_time asc, end_time asc) as lga_end_time
from test02
) t
) t
) t
group by grp_id
2 Resumen
Esta pregunta es sobre la fusión de intervalos. El problema es bastante clásico. La idea central del juicio es construir la condición:
La hora de inicio de la fila actual <= la hora de finalización de la fila anterior (ordenada en orden descendente por hora de inicio y hora de finalización).
Luego use la idea clásica de agrupación para encontrar los valores mínimos y máximos en un grupo.