sql >> Databáze >  >> RDS >> Mysql

MySQL konsolidující řádky tabulky s překrývajícími se rozsahy dat

Jedním ze způsobů, jak toho dosáhnout, je použití korelovaných poddotazů:

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 predikáty korelovaných poddotazů:

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

vrátit všechny překrývající se záznamy související s aktuálním záznamem. Provedením agregace těchto záznamů můžeme najít počáteční / koncová data každého intervalu:počáteční datum intervalu je minimum opens datum mezi všemi překrývajícími se záznamy, zatímco koncové datum je maximální closes datum.

Ukázka zde

UPRAVIT:

Výše uvedené řešení nebude fungovat se sadou intervalů, jako je tato:

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

Záznam č. 2, při zpracování vytvoří chybný počáteční/koncový interval.

Zde je řešení pomocí proměnných:

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

Cílem je začít od opens/closes úplně vlevo časový úsek. Proměnné @start , @end se používají k šíření přírůstkově se rozšiřujícího (jak se zpracovávají nové překrývající se řádky) konsolidovaného intervalu v řetězci intervalů. Jakmile je zjištěn nepřekrývající se interval, [@start - @end] je inicializován tak, aby odpovídal tomuto novému intervalu a grp se zvýší o jedna.

Ukázka zde




  1. Zkontrolujte, zda na tabulku odkazuje cizí klíč na serveru SQL pomocí OBJECTPROPERTY()

  2. doctrine2:jak převést jeden k mnoha na mnoho k mnoha bez ztráty dat

  3. Kdy použít LEFT JOIN a kdy INNER JOIN?

  4. Tabulky a indexy vs. HDD a SSD