Mysql
 sql >> Database >  >> RDS >> Mysql

MySQL che consolida le righe della tabella con intervalli di date sovrapposti

Un modo per farlo è l'uso di sottoquery correlate:

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

Il WHERE predicati delle subquery correlate:

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

restituire tutti i record sovrapposti relativi al record corrente. Eseguendo l'aggregazione di uno di questi record possiamo trovare le date di inizio/fine di ciascun intervallo:la data di inizio dell'intervallo è il minimo opens data tra tutti i record sovrapposti, mentre la data di fine è il massimo closes data.

Dimostrazione qui

MODIFICA:

La soluzione precedente non funzionerà con un insieme di intervalli come il seguente:

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

Registrazione n. 2, una volta elaborato, produrrà un intervallo di inizio/fine errato.

Ecco una soluzione che utilizza le variabili:

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

L'idea è di iniziare da opens/closes più a sinistra intervallo. Variabili @start , @end vengono utilizzati per propagare l'intervallo consolidato in espansione incrementale (mentre vengono elaborate nuove righe sovrapposte) lungo la catena di intervalli. Quando viene rilevato un intervallo non sovrapposto, [@start - @end] viene inizializzato in modo da abbinare questo nuovo intervallo e grp viene incrementato di uno.

Dimostrazione qui