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

MySQL konsoliderer tabelrækker med overlappende datospænd

En måde at gøre det på er ved at bruge korrelerede underforespørgsler:

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
 

WHERE prædikater for de korrelerede underforespørgsler:

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

returnere alle overlappende poster relateret til den aktuelle post. Ved at aggregere en af ​​disse poster kan vi finde start-/slutdatoerne for hvert interval:startdatoen for intervallet er minimum opens dato mellem alle overlappende poster, hvorimod slutdatoen er den maksimale closes dato.

Demo her

EDIT:

Ovenstående løsning virker ikke med et sæt intervaller som følgende:

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

Rekordnr. 2, når den behandles, vil det frembringe et mangelfuldt start/slut interval.

Her er en løsning, der bruger variabler:

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
 

Ideen er at starte fra længst til venstre opens/closes interval. Variabler @start , @end bruges til at udbrede det trinvist udvidende (efterhånden som nye overlappende rækker behandles) konsoliderede interval ned i intervalkæden. Når et ikke-overlappende interval er stødt på, [@start - @end] initialiseres for at matche dette nye interval og grp øges med én.

Demo her




  1. Naturlig sortering, der understøtter store tal

  2. Sender SentryOne-data til Azure SQL Database DTU Calculator

  3. Sådan konverteres til store bogstaver i MariaDB

  4. mysql viser ledige tidsslots og tidsslot optaget fra bordet