restriccion - operaciones con fechas sql
¿Cuál es una forma simple y eficiente de encontrar filas con superposiciones de intervalos de tiempo en SQL? (3)
Tengo dos tablas, ambas con campos de hora de inicio y hora de finalización. Necesito encontrar, para cada fila en la primera tabla, todas las filas en la segunda tabla donde los intervalos de tiempo se cruzan.
Por ejemplo:
<-----row 1 interval------->
<---find this--> <--and this--> <--and this-->
Por favor, pronuncie su respuesta en la forma de un SQL WHERE
-clause, Y considere el caso donde el tiempo de finalización en la segunda tabla puede ser NULL
.
La plataforma objetivo es SQL Server 2005, pero las soluciones de otras plataformas también pueden ser de interés.
Suena muy complicado hasta que empiezas a trabajar desde el reverso. A continuación, ilustré SOLAMENTE BUENOS CASOS (¡no se superponen)! definido por esas 2 condiciones simples, no tenemos rangos de solapamiento si condA O condB es VERDADERO, entonces vamos a revertir los siguientes: NO condA Y NO CondB, en nuestro caso acabo de invertir los signos (> se convirtió en <=)
/*
|--------| A /___ CondA: b.ddStart > a.ddEnd
|=========| B / /____ CondB: a.ddS > b.ddE
|+++++++++| A /
*/
--DROP TABLE ran
create table ran ( mem_nbr int, ID int, ddS date, ddE date)
insert ran values
(100, 1, ''2012-1-1'',''2012-12-30''), ----/ ovl
(100, 11, ''2012-12-12'',''2012-12-24''), ----/
(100, 2, ''2012-12-31'',''2014-1-1''),
(100, 3, ''2014-5-1'',''2014-12-14'') ,
(220, 1, ''2015-5-5'',''2015-12-14'') , ---/ovl
(220, 22, ''2014-4-1'',''2015-5-25'') , ---/
(220, 3, ''2016-6-1'',''2016-12-16'')
select DISTINCT a.mem_nbr , a.* , ''-'' [ ], b.dds, b.dde, b.id
FROM ran a
join ran b on a.mem_nbr = b.mem_nbr -- match by mem#
AND a.ID <> b.ID -- itself
AND b.ddS <= a.ddE -- NOT b.ddS > a.ddE
AND a.ddS <= b.ddE -- NOT a.ddS > b.ddE
SELECT *
FROM table1,table2
WHERE table2.start <= table1.end
AND (table2.end IS NULL OR table2.end >= table1.start)
select * from table_1
right join
table_2 on
(
table_1.start between table_2.start and table_2.[end]
or
table_1.[end] between table_2.start and table_2.[end]
or
(table_1.[end] > table_2.start and table_2.[end] is null)
)
EDITAR: Ok, no vayas por mi solución, funciona como una mierda. La solución "donde" es 14 veces más rápida. Oops ...
Algunas estadísticas: ejecutarse en un DB con ~ 65000 registros para la tabla 1 y 2 (sin indexación), con intervalos de 2 días entre el inicio y el final de cada fila, ejecutándose durante 2 minutos en SQLSMSE (no tengo paciencia para esperar )
Usando join: 8356 filas en 2 minutos
Usando donde: 115436 filas en 2 minutos