Алгоритм объединения / слияния диапазонов дат

Я пытаюсь найти лучший способ объединить диапазоны дат в одну запись базы данных (элемент массива).

Это данные, которые у меня есть:

Array ( [0] => Array ( [id] => 18298 [start_date] => 2011-07-09 [end_date] => 2011-10-01 ) [1] => Array ( [id] => 18297 [start_date] => 2011-06-01 [end_date] => 2011-06-30 ) [2] => Array ( [id] => 17113 [start_date] => 2011-03-31 [end_date] => 2011-05-31 ) [3] => Array ( [id] => 20555 [start_date] => 2011-01-03 [end_date] => 2011-03-31 ) ) 

И после того, как мы их объединим, массив (или база данных) должен выглядеть так:

 Array ( [0] => Array ( [merged_ids] => 18298 [start_date] => 2011-07-09 [end_date] => 2011-10-01 ) [1] => Array ( [merged_ids] => 18297, 17113, 20555 [start_date] => 2011-01-03 [end_date] => 2011-06-30 ) ) 

Есть ли какой-либо алгоритм для прохождения всех элементов / диапазонов и их комбинирования? Какой способ лучше / проще сделать – через базу данных (MYSQL) или кодирование (PHP)?

Любые рекомендации очень ценятся.

Благодаря!

UPDATE: Извините, я не предоставил достаточно информации: мы должны объединить любые непрерывные и перекрывающиеся диапазоны дат.

Сортировка по дате начала.

Затем выполните итерацию и проверьте, есть ли дата начала следующего элемента до или непосредственно после текущей даты окончания. Если это так, то слейте следующий в текущий. Затем продолжайте.

Я написал функцию, которая объединяет / объединяет список диапазонов. Он написан на Python, но его легко переписать в PHP. Вот полный код: https://gist.github.com/barszczmm/8447665 и вот упрощенный алгоритм (все еще в Python):

 list_of_ranges.sort() # sort input list new_list_of_ranges = [] # output list new_range_item_start = None new_range_item_end = None length = len(list_of_ranges) for i, range_item in enumerate(list_of_ranges): if new_range_item_start is None: new_range_item_start = range_item[0] new_range_item_end = range_item[1] elif new_range_item_end >= range_item[0]: new_range_item_end = max(range_item[1], new_range_item_end) else: new_list_of_ranges.append((new_range_item_start, new_range_item_end)) new_range_item_start = range_item[0] new_range_item_end = range_item[1] # save if this is last item if i + 1 == length: new_list_of_ranges.append((new_range_item_start, new_range_item_end)) 

Реализация подобна:

 function mergeDateTimeRanges($ranges) { $retVal = []; //sort date ranges by begin time usort($ranges, function ($a, $b) { return strcmp($a['begin_at'], $b['begin_at']); }); $currentRange = []; foreach ($ranges as $range) { // bypass invalid value if ($range['begin_at'] >= $range['end_at']) { continue; } //fill in the first element if (empty($currentRange)) { $currentRange = $range; continue; } if ($currentRange['end_at'] < $range['begin_at']) { $retVal[] = $currentRange; $currentRange = $range; } elseif ($currentRange['end_at'] < $range['end_at']) { $currentRange ['end_at'] = $range['end_at']; } } if ($currentRange) { $retVal[] = $currentRange; } return $retVal; }