rango por mayor insertar filtrar fechas fecha entre consulta comparar sql mysql date

por - sql server comparar fechas mayor



ComparaciĆ³n de los intervalos de fechas (10)

Creé una función para tratar este problema en MySQL. Simplemente convierta las fechas en segundos antes de usar.

DELIMITER ;; CREATE FUNCTION overlap_interval(x INT,y INT,a INT,b INT) RETURNS INTEGER DETERMINISTIC BEGIN DECLARE overlap_amount INTEGER; IF (((x <= a) AND (a < y)) OR ((x < b) AND (b <= y)) OR (a < x AND y < b)) THEN IF (x < a) THEN IF (y < b) THEN SET overlap_amount = y - a; ELSE SET overlap_amount = b - a; END IF; ELSE IF (y < b) THEN SET overlap_amount = y - x; ELSE SET overlap_amount = b - x; END IF; END IF; ELSE SET overlap_amount = 0; END IF; RETURN overlap_amount; END ;; DELIMITER ;

En MySQL, si tengo una lista de rangos de fechas (range-start y range-end). p.ej

10/06/1983 to 14/06/1983 15/07/1983 to 16/07/1983 18/07/1983 to 18/07/1983

Y quiero verificar si otro rango de fechas contiene CUALQUIERA de los rangos que ya están en la lista, ¿cómo lo haría?

p.ej

06/06/1983 to 18/06/1983 = IN LIST 10/06/1983 to 11/06/1983 = IN LIST 14/07/1983 to 14/07/1983 = NOT IN LIST


En tus resultados esperados dices

06/06/1983 a 18/06/1983 = EN LA LISTA

Sin embargo, este período no contiene ni está contenido en ninguno de los períodos en su tabla (¡no en la lista!) De períodos. Sin embargo, se superpone el período del 10/06/1983 al 14/06/1983.

Puede encontrar el libro Snodgrass ( http://www.cs.arizona.edu/people/rts/tdbbook.pdf ) útil: es anterior a mysql pero el concepto de tiempo no ha cambiado ;-)


Este es un problema clásico, y en realidad es más fácil si revierte la lógica.

Dejame darte un ejemplo.

Voy a publicar un período de tiempo aquí, y todas las diferentes variaciones de otros períodos que se superponen de alguna manera.

|-------------------| compare to this one |---------| contained within |----------| contained within, equal start |-----------| contained within, equal end |-------------------| contained within, equal start+end |------------| not fully contained, overlaps start |---------------| not fully contained, overlaps end |-------------------------| overlaps start, bigger |-----------------------| overlaps end, bigger |------------------------------| overlaps entire period

por otro lado, permítanme publicar todos los que no se superponen:

|-------------------| compare to this one |---| ends before |---| starts after

Entonces, si simplemente reduce la comparación a:

starts after end ends before start

luego encontrarás todos aquellos que no se superponen, y luego encontrarás todos los períodos que no coinciden.

Para su ejemplo final NOT IN LIST, puede ver que coincide con esas dos reglas.

Tendrá que decidir si los siguientes períodos están dentro o fuera de sus rangos:

|-------------| |-------| equal end with start of comparison period |-----| equal start with end of comparison period

Si su tabla tiene columnas llamadas range_end y range_start, aquí hay algunos SQL simples para recuperar todas las filas coincidentes:

SELECT * FROM periods WHERE NOT (range_start > @check_period_end OR range_end < @check_period_start)

Tenga en cuenta el NO allí. Como las dos reglas simples encuentran todas las filas que no coinciden , un simple NOT lo invertirá para decir: si no es una de las filas que no coinciden, tiene que ser una de las que coincidan .

Aplicando la lógica de reversión simple aquí para deshacerte del NOT y terminarás con:

SELECT * FROM periods WHERE range_start <= @check_period_end AND range_end >= @check_period_start


Mire en el siguiente ejemplo. Te será útil.

SELECT DISTINCT RelatedTo,CAST(NotificationContent as nvarchar(max)) as NotificationContent, ID, Url, NotificationPrefix, NotificationDate FROM NotificationMaster as nfm inner join NotificationSettingsSubscriptionLog as nfl on nfm.NotificationDate between nfl.LastSubscribedDate and isnull(nfl.LastUnSubscribedDate,GETDATE()) where ID not in(SELECT NotificationID from removednotificationsmaster where Userid=@userid) and nfl.UserId = @userid and nfl.RelatedSettingColumn = RelatedTo


Otro método al usar BETWEEN sentencia sql

Períodos incluidos:

SELECT * FROM periods WHERE @check_period_start BETWEEN range_start AND range_end AND @check_period_end BETWEEN range_start AND range_end

Periodos excluidos:

SELECT * FROM periods WHERE (@check_period_start NOT BETWEEN range_start AND range_end OR @check_period_end NOT BETWEEN range_start AND range_end)


Pruebe esto en MS SQL

WITH date_range (calc_date) AS ( SELECT DATEADD(DAY, DATEDIFF(DAY, 0, [ending date]) - DATEDIFF(DAY, [start date], [ending date]), 0) UNION ALL SELECT DATEADD(DAY, 1, calc_date) FROM date_range WHERE DATEADD(DAY, 1, calc_date) <= [ending date]) SELECT P.[fieldstartdate], P.[fieldenddate] FROM date_range R JOIN [yourBaseTable] P on Convert(date, R.calc_date) BETWEEN convert(date, P.[fieldstartdate]) and convert(date, P.[fieldenddate]) GROUP BY P.[fieldstartdate], P.[fieldenddate];


Si su RDBMS es compatible con la función OVERLAP (), esto se convierte en algo trivial, sin necesidad de soluciones propias. (En Oracle, aparentemente funciona pero no está documentado).


Tomando su rango de ejemplo del 06/06/1983 al 18/06/1983 y suponiendo que tiene columnas llamadas inicio y fin para sus rangos, puede usar una cláusula como esta

where (''1983-06-06'' <= end) and (''1983-06-18'' >= start)

es decir, verifique que el inicio de su rango de prueba esté antes del final del rango de la base de datos, y que el final de su rango de prueba esté después o al comienzo del rango de la base de datos.


CREATE FUNCTION overlap_date(s DATE, e DATE, a DATE, b DATE) RETURNS BOOLEAN DETERMINISTIC RETURN s BETWEEN a AND b or e BETWEEN a and b or a BETWEEN s and e;


SELECT * FROM tabla a WHERE ( @Fini <= a.dFechaFin AND @Ffin >= a.dFechaIni ) AND ( (@Fini >= a.dFechaIni AND @Ffin <= a.dFechaFin) OR (@Fini >= a.dFechaIni AND @Ffin >= a.dFechaFin) OR (a.dFechaIni>=@Fini AND a.dFechaFin <=@Ffin) OR (a.dFechaIni>=@Fini AND a.dFechaFin >=@Ffin) )