My method will generate a combined array where, by overlapping or sequential dates, are grouped together, and the group identifiers are stored as a string of comma-separated values.
I use the modern "spaceship operator" ( <=> ) to compare usort() . If your code runs below version php7, you can use:
usort($array,function($a,$b){ return strcmp($a['start_date'],$b['start_date']); });
See inline comments for a step-by-step explanation.
Code: ( Demo )
function mergeRanges($array){ usort($array,function($a,$b){ return $a['start_date']<=>$b['start_date']; }); // order by start_date ASC foreach($array as $i=>$row){ if($i && $row['start_date']<=date('Ym-d',strtotime("{$result[$x]['end_date']} +1 day"))){ // not the first iteration and dates are within current group range if($row['end_date']>$result[$x]['end_date']){ // only if current end_date is greater than existing end_date $result[$x]['end_date']=$row['end_date']; // overwrite end_date with new end_date in group } $result[$x]['merged_ids'][]=$row['id']; // append id to merged_ids subarray }else{ // first iteration or out of range; start new group if($i){ // if not first iteration $result[$x]['merged_ids']=implode(', ',$result[$x]['merged_ids']); // convert previous group id elements to csv string }else{ // first iteration $x=-1; // declare $x as -1 so that it becomes 0 when incremented with ++$x } $result[++$x]=['merged_ids'=>[$row['id']],'start_date'=>$row['start_date'],'end_date'=>$row['end_date']]; // declare new group } } $result[$x]['merged_ids']=implode(', ',$result[$x]['merged_ids']); // convert final merged_ids subarray to csv string return $result; } $array=[ ['id'=>18298,'start_date'=>'2011-07-09','end_date'=>'2011-10-01'], ['id'=>18297,'start_date'=>'2011-06-01','end_date'=>'2011-06-30'], ['id'=>17113,'start_date'=>'2011-03-31','end_date'=>'2011-05-31'], // tests that 17113 and 18297 belong in same group ['id'=>20556,'start_date'=>'2011-02-03','end_date'=>'2011-02-13'], // tests that "fully overlapped" date range is included ['id'=>20555,'start_date'=>'2011-01-03','end_date'=>'2011-03-31'] ]; print_r(mergeRanges($array));
Output:
Array ( [0] => Array ( [merged_ids] => 20555, 20556, 17113, 18297 [start_date] => 2011-01-03 [end_date] => 2011-06-30 ) [1] => Array ( [merged_ids] => 18298 [start_date] => 2011-07-09 [end_date] => 2011-10-01 ) )