tipo - Comprobar la superposición de rangos de fechas en MySQL
rango de fechas codeigniter (6)
Esta tabla se usa para almacenar sesiones (eventos):
CREATE TABLE session (
id int(11) NOT NULL AUTO_INCREMENT
, start_date date
, end_date date
);
INSERT INTO session
(start_date, end_date)
VALUES
("2010-01-01", "2010-01-10")
, ("2010-01-20", "2010-01-30")
, ("2010-02-01", "2010-02-15")
;
No queremos tener conflicto entre rangos.
Digamos que necesitamos insertar una nueva sesión del 2010-01-05 al 2010-01-25 .
Nos gustaría saber la (s) sesión (es) conflictiva (s).
Aquí está mi consulta:
SELECT *
FROM session
WHERE "2010-01-05" BETWEEN start_date AND end_date
OR "2010-01-25" BETWEEN start_date AND end_date
OR "2010-01-05" >= start_date AND "2010-01-25" <= end_date
;
Aquí está el resultado:
+----+------------+------------+
| id | start_date | end_date |
+----+------------+------------+
| 1 | 2010-01-01 | 2010-01-10 |
| 2 | 2010-01-20 | 2010-01-30 |
+----+------------+------------+
¿Hay una mejor manera de obtener eso?
Dado dos intervalos como (s1, e1) y (s2, e2) con s1 <e1 y s2 <e2
Puede calcular la superposición de esta manera:
SELECT
s1, e1, s2, e2,
ABS(e1-s1) as len1,
ABS(e2-s2) as len2,
GREATEST(LEAST(e1, e2) - GREATEST(s1, s2), 0)>0 as overlaps,
GREATEST(LEAST(e1, e2) - GREATEST(s1, s2), 0) as overlap_length
FROM test_intervals
También funcionará si un intervalo está dentro del otro.
La respuesta de Lamy es buena, pero puedes optimizarla un poco más.
SELECT * FROM tbl WHERE
existing_start BETWEEN $newSTart AND $newEnd OR
$newStart BETWEEN existing_start AND existing_end
Esto capturará los cuatro escenarios donde los rangos se superponen y excluye los dos donde no lo hacen.
Me enfrenté al problema similar. Mi problema era dejar de reservar entre una variedad de fechas bloqueadas. Por ejemplo, la reserva está bloqueada para una propiedad entre el 2 de mayo y el 7 de mayo. Necesitaba encontrar cualquier tipo de fecha de superposición para detectar y detener la reserva. Mi solución es similar a LordJavac.
SELECT * FROM ib_master_blocked_dates WHERE venue_id=$venue_id AND
(
(mbd_from_date BETWEEN ''$from_date'' AND ''$to_date'')
OR
(mbd_to_date BETWEEN ''$from_date'' AND ''$to_date'')
OR
(''$from_date'' BETWEEN mbd_from_date AND mbd_to_date)
OR
(''$to_date'' BETWEEN mbd_from_date AND mbd_to_date)
)
*mbd=master_blocked_dates
Avísame si no funciona.
Recientemente tuve problemas con el mismo problema y terminé con este simple paso (Esto puede no ser un buen enfoque o consumir memoria) -
SELECT * FROM duty_register WHERE employee = ''2'' AND (
(
duty_start_date BETWEEN {$start_date} AND {$end_date}
OR
duty_end_date BETWEEN {$start_date} AND {$end_date}
)
OR
(
{$start_date} BETWEEN duty_start_date AND duty_end_date
OR
{$end_date} BETWEEN duty_start_date AND duty_end_date)
);
Esto me ayudó a encontrar las entradas con intervalos de fechas superpuestas.
Espero que esto ayude a alguien.
Tenía una consulta con una aplicación de calendario que una vez escribí. Creo que utilicé algo como esto:
... WHERE new_start < existing_end
AND new_end > existing_start;
ACTUALIZAR Esto definitivamente debería funcionar ((ns, ne, es, ee) = (new_start, new_end, existing_start, existing_end)):
- ns - ne - es - ee: no se superpone y no coincide (porque ne <es)
- ns - es - ne - ee: superposiciones y coincidencias
- es - ns - ee - ne: superposiciones y coincidencias
- es - ee - ns - ne: no se superpone y no coincide (porque ns> ee)
- es - ns - ne - ee: superposiciones y coincidencias
- ns - es - ee - ne: superposiciones y coincidencias
Aquí hay un fiddle
SELECT * FROM tbl WHERE
existing_start BETWEEN $newStart AND $newEnd OR
existing_end BETWEEN $newStart AND $newEnd OR
$newStart BETWEEN existing_start AND existing_end
if (!empty($result))
throw new Exception(''We have overlapping'')
Estas 3 líneas de cláusulas sql cubren los 4 casos de superposición requeridos.