Preguntas de fusión de intervalo en preguntas de entrevista de SQL

Tabla de contenido

0 necesidades

1 Preparación de datos

2 Análisis de datos

 2 Resumen


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.

Supongo que te gusta

Origin blog.csdn.net/godlovedaniel/article/details/126662876
Recomendado
Clasificación