sql >> Base de Datos >  >> RDS >> Mysql

Filas de la tabla de consolidación de MySQL con intervalos de fechas superpuestos

Una forma de hacerlo es mediante el uso de subconsultas correlacionadas:

SELECT DISTINCT
       (SELECT MIN(opens)
       FROM mytable AS t2
       WHERE t2.opens <= t1.closes AND t2.closes >= t1.opens) AS start,
       (SELECT MAX(closes)
       FROM mytable AS t2
       WHERE t2.opens <= t1.closes AND t2.closes >= t1.opens) AS end       
FROM mytable AS t1
ORDER BY opens

El WHERE predicados de las subconsultas correlacionadas:

t2.opens <= t1.closes AND t2.closes >= t1.opens

devolver todos los registros superpuestos relacionados con el registro actual. Realizando la agregación de estos registros podemos encontrar las fechas de inicio/finalización de cada intervalo:la fecha de inicio del intervalo es la mínima opens fecha entre todos los registros superpuestos, mientras que la fecha de finalización es la máxima closes fecha.

Demostración aquí

EDITAR:

La solución anterior no funcionará con un conjunto de intervalos como el siguiente:

1. |-----------|
2. |----|
3.           |-----|

Nro. de registro 2, cuando se procese, producirá un intervalo de inicio/fin defectuoso.

Aquí hay una solución usando variables:

SELECT MIN(start) AS start, MAX(end) AS end
FROM (
  SELECT @grp := IF(@start = '1900-01-01' OR 
                   (opens <= @end AND closes >= @start), @grp, @grp+1) AS grp,        
         @start := IF(@start = '1900-01-01', opens, 
                      IF(opens <= @end AND closes >= @start, 
                         IF (@start < opens, @start, opens), opens)) AS start,
         @end := IF(@end = '1900-01-01', closes, 
                    IF (opens <= @end AND closes >= @start, 
                      IF (@end > closes, @end, closes), closes)) AS end                 
  FROM mytable
  CROSS JOIN (SELECT @grp := 1, @start := '1900-01-01', @end := '1900-01-01') AS vars
  ORDER BY opens, DATEDIFF(closes, opens) DESC) AS t
GROUP BY grp

La idea es comenzar desde el extremo izquierdo opens/closes intervalo. Variables @start , @end se utilizan para propagar el intervalo consolidado de expansión incremental (a medida que se procesan nuevas filas superpuestas) a lo largo de la cadena de intervalos. Una vez que se encuentra un intervalo que no se superpone, [@start - @end] se inicializa para que coincida con este nuevo intervalo y grp se incrementa en uno.

Demostración aquí