2016-07-11 11 views
1

Ich habe eine Tabelle "Lessons_holidays". Es kann mehrere Feriendatumsbereiche enthalten heißtWie überlappende Datumsbereiche in MySQL kombinieren?

"holiday_begin" "holiday_end" 
2016-06-15   2016-06-15 
2016-06-12   2016-06-16 
2016-06-15   2016-06-19 
2016-06-29   2016-06-29 

ich jeden Eintrag kombinieren möchten, wenn die Datumsbereiche überlappen. Und ich brauche eine Ausgabe wie folgt:

"holiday_begin" "holiday_end" 
2016-06-12   2016-06-19 
2016-06-29   2016-06-29 

SQL: Die folgende sql-Anweisung lädt alle Zeilen. Jetzt bin ich fest.

SELECT lh1.holiday_begin, lh1.holiday_end 
FROM local_lessons_holidays lh1 
WHERE lh1.holiday_impact = '1' AND 
(DATE_FORMAT(lh1.holiday_begin, '%Y-%m') <= '2016-06' AND DATE_FORMAT(lh1.holiday_end, '%Y-%m') >= '2016-06') AND 
lh1.uid = '1' 
+0

Dies ist ziemlich schwierig in MySQL zu tun. Haben Sie andere Datenbanken, die Sie verwenden können? –

Antwort

2

Dies ist ein hartes Problem, das schwieriger gemacht wird, weil Sie MySQL verwenden. Hier ist eine Idee. Finden Sie das Anfangsdatum aller Feiertage in jeder Gruppe. Dann behandelt eine kumulative Summe des Flags für den "Anfang" die Gruppen. Der Rest ist nur Aggregation.

Folgendes sollte das tun, was Sie wollen, vorausgesetzt, Sie sind keine doppelten Datensätze:

select min(holiday_begin) as holiday_begin, max(holiday_end) as holiday_end 
from (select lh.*, (@grp := @grp + group_flag) as grp 
     from (select lh.*, 
        (case when not exists (select 1 
              from lessons_holidays lh2 
              where lh2.holiday_begin <= lh.holiday_end and 
               lh2.holiday_end > lh.holiday_begin and 
               (lh2.holiday_begin <> lh.holiday_begin or 
               lh2.holiday_end < lh.holiday_end) 

             ) 
         then 1 else 0 
        end) as group_flag 
      from lessons_holidays lh 
      ) lh cross join 
      (select @grp := 0) params 
     order by holiday_begin, holiday_end 
    ) lh 
group by grp; 

Wenn Sie Duplikate haben, verwenden Sie nur select distinct auf den innersten Verweise auf den Tisch.

Here ist eine SQL Fiddle.

EDIT:

Diese Version erscheint, besser zu arbeiten:

select min(holiday_begin) as holiday_begin, max(holiday_end) as holiday_end 
from (select lh.*, (@grp := @grp + group_flag) as grp 
     from (select lh.*, 
        (case when not exists (select 1 
              from lessons_holidays lh2 
              where lh2.holiday_begin <= lh.holiday_begin and 
               lh2.holiday_end > lh.holiday_begin and 
               lh2.holiday_begin <> lh.holiday_begin and 
               lh2.holiday_end <> lh.holiday_end 
             ) 
         then 1 else 0 
        end) as group_flag 
      from lessons_holidays lh 
      ) lh cross join 
      (select @grp := 0) params 
     order by holiday_begin, holiday_end 
    ) lh 
group by grp; 

Wie here dargestellt.

+0

Vielen Dank. Ich werde es später ausprobieren. – Bonaparte

+0

Als Ergebnis bekomme ich nur: 2016-06-12 | 2016-06-29. Dieses Ergebnis kann ich auch durch diese SQL-Anweisung erhalten: "SELECT MIN (holiday_begin) als holiday_begin, MAX (holiday_end) als holiday_end FROM local_lessons_holidays WHERE 1" – Bonaparte

+0

@ Bonaparte. . . Fest. Das Problem war die Überlappungslogik. –