2016-07-11 2 views
1

У меня есть таблица «lessons_holidays». Он может содержать несколько диапазонов дат праздника т.е.Как совместить перекрывающиеся диапазоны дат в MySQL?

"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 

Я хотел бы объединить каждую запись, если диапазоны дат перекрывают друг другу. И мне нужен вывод следующим образом:

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

SQL: Следующий SQL-оператор загружает все строки. Теперь я застрял.

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

Это довольно сложно сделать в MySQL. У вас есть другие базы данных, которые вы можете использовать? –

ответ

2

Это сложная проблема, сделанная сложнее, потому что вы используете MySQL. Вот идея. Найдите дату начала всех праздников в каждой группе. Тогда кумулятивная сумма флага для «начала» обрабатывает группы. Остальное - просто агрегация.

Следующие должны делать то, что вы хотите, предполагая, что у вас нет повторяющихся записей:

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; 

Если у вас есть дубликаты, просто использовать select distinct на сокровенные ссылки на таблицу.

Here - это скрипт SQL.

EDIT:

Эта версия, кажется, работает лучше:

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; 

Как показано here.

+0

Большое спасибо. Я попробую это позже. – Bonaparte

+0

В результате я получаю только: 2016-06-12 | 2016-06-29. этот результат можно получить и в этом заявлении sql: «SELECT MIN (holiday_begin) как holiday_begin, MAX (holiday_end) как holiday_end FROM local_lessons_holidays ГДЕ 1» – Bonaparte

+0

@Bonaparte. , , Исправлена. Проблема заключалась в логике перекрытия. –

Смежные вопросы