sql >> Database >  >> RDS >> Mysql

MySQL-consolidatietabelrijen met overlappende periodes

Een manier om dit te doen is door het gebruik van gecorreleerde subquery's:

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

De WHERE predikaten van de gecorreleerde subquery's:

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

alle overlappende records met betrekking tot de huidige record retourneren. Door aggregatie van een van deze records uit te voeren, kunnen we de start- / einddatums van elk interval vinden:de startdatum van het interval is het minimum opens datum tussen alle overlappende records, terwijl de einddatum het maximum is closes datum.

Demo hier

BEWERKEN:

De bovenstaande oplossing werkt niet met een reeks intervallen zoals de volgende:

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

Opname nr. 2, wanneer verwerkt, zal een gebrekkig begin/eind interval produceren.

Hier is een oplossing die variabelen gebruikt:

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

Het idee is om te beginnen vanaf de meest linkse opens/closes interval. Variabelen @start , @end worden gebruikt om het incrementeel uitbreidende (terwijl nieuwe overlappende rijen worden verwerkt) geconsolideerde interval in de intervalketen te verspreiden. Zodra een niet-overlappend interval is gevonden, [@start - @end] wordt geïnitialiseerd om overeen te komen met dit nieuwe interval en grp wordt met één verhoogd.

Demo hier




  1. kan handelsmerksymbool niet weergeven in mysql naar html

  2. Hoe maak je twee kolommen voor automatisch ophogen in MySQL?

  3. Hoe SUBSTRING_INDEX() werkt in MariaDB

  4. Fout bij het installeren van de app met mysql2 gem