Группировка и сумма из двух массивов

Я просматриваю результирующие множества из двух хранимых процедур, получая окончательные результаты на основе полей в рамках обеих процедур.

Ниже приведены два набора результатов:

-Получить всех $customers с данными или без них:

 | id | name | parentID | calls | duration | type | +----+---------+----------+-------+----------+-------+ | 8 | Telekom | 80 | 100 | 3000 | 01-02 | | 8 | Telekom | 80 | 10 | 700 | 080 | | 8 | Telekom | 80 | 5 | 100 | 05 | | 16 | Orange | 7 | 50 | 2200 | 03 | | 16 | Orange | 7 | NULL | NULL | NULL | | 9 | Verizon | 2 | NULL | NULL | NULL | | 18 | T&T | 108 | 30 | 1200 | 04 | | 20 | Sprint | 33 | 120 | 4000 | 09 | | 20 | Sprint | 33 | 60 | 3500 | 01-02 | | 17 | CellCom | 99 | NULL | NULL | NULL | | 1 | T-Mobile| 14 | 85 | 2600 | 087 | | 1 | T-Mobile| 14 | 2 | 30 | 07 | | 34 | US-Cell | 27 | 240 | 1700 | 084 | 

-Получить все $subcustomers с данными

 | id | name | parentID | calls | duration | type | +----+---------------+----------+-------+----------+-------+ | 44 | CallMe | 8 | 20 | 400 | 01-02 | | 44 | CallMe | 8 | 5 | 20 | 080 | | 44 | CallMe | 8 | 15 | 200 | 087 | | 72 | DialNow | 16 | 100 | 2000 | 03 | | 72 | DialNow | 16 | 5 | 100 | 04 | | 13 | Online4U | 9 | 10 | 25 | 05 | | 22 | TeleSolutions | 9 | 30 | 200 | 05 | | 4 | FonezInc | 9 | 5 | 5 | 084 | | 10 | Digi | 20 | 100 | 4000 | 09 | | 11 | Vodafone | 20 | 40 | 2400 | 08 | 

Желаемый результат должен быть следующим:

-Добавить все вызовы / продолжительность субклиентов для клиентов (если subcustomer.parentID = customer.id), против правильного type , в противном случае показать клиентам данные.
-Если у клиента нет вызовов / типов (NULL) и у субклиентов с вызовами, добавьте их клиенту.
-Если у субклиента есть разные типы вызовов, добавьте их к клиенту
-Типы динамичны, мы не сейчас, что / сколько типов там будет
Как показано ниже:

 | id | name | parentID | calls | duration | type | +----+---------+----------+-------+----------+-------+ | 8 | Telekom | 80 | 120 | 3400 | 01-02 | | 8 | Telekom | 80 | 15 | 720 | 080 | | 8 | Telekom | 80 | 5 | 100 | 05 | | 8 | Telekom | 80 | 15 | 200 | 087 | | 16 | Orange | 7 | 150 | 4200 | 03 | | 16 | Orange | 7 | 5 | 100 | 04 | | 9 | Verizon | 2 | 40 | 225 | 05 | | 9 | Verizon | 2 | 5 | 5 | 084 | | 18 | T&T | 108 | 30 | 1200 | 04 | | 20 | Sprint | 33 | 220 | 4000 | 09 | | 20 | Sprint | 33 | 60 | 3500 | 01-02 | | 20 | Sprint | 33 | 40 | 2400 | 08 | | 1 | T-Mobile| 14 | 85 | 2600 | 087 | | 1 | T-Mobile| 14 | 2 | 30 | 07 | | 34 | US-Cell | 27 | 240 | 1700 | 084 | 

Идея состоит в том, чтобы группировать subcustomers и customers во временных ассоциативных массивах с помощью parentID и ID качестве ключей. После этого мы можем построить результат.

Вход 1 : Вот некоторые фиктивные данные для временного массива субклиентов .
Этот массив содержит вызовы, сгруппированные по parentId (первый уровень) и тип вызова (второй уровень). Он имеет следующую структуру:

 [parentID] => Array ( [type] => Array // eg type = 03 ( [calls] => value //calls of type 03 [duration] => value //duration of type 03 ) [type] => Array //eg type = 087 ( [calls] => value //calls of type 087 [duration] => value //duration of type 087 ) ... ) 

Ниже приведен код, создающий темп. массив субклиентов:

 $tempS = array(); foreach($subcustomers as $subcustomer) { $parentId = $subcustomer['parentID']; $calls = $subcustomer['calls']; $type = $subcustomer['type']; $duration = $subcustomer['duration']; //if id/type is insered yet if(array_key_exists($parentId, $tempS) && array_key_exists($type, $tempS[$parentId])) { $tempS[$parentId][$type]['calls'] += $calls; $tempS[$parentId][$type]['duration'] += $duration; } else { $tempS[$parentId][$type]['calls'] = $calls; $tempS[$parentId][$type]['duration'] = $duration; } } 

Вход 2 : Вот фиктивные данные для temp. массив клиентов . Структура этого массива выглядит следующим образом:

 [id] => Array ( [name] => 'Telekom' [parentID] => 80 [calls] => Array ( [type] => // eg calls of type 01-02 [type] => // eg calls of type 05 ) [duration] => Array ( [type] => //duration of type 01-02 [type] => //duration of type 05 ) ) 

Вот код для temp. массив клиентов:

 $tempC = array(); foreach($customers as $customer) { $id = $customer['id']; $name = $customer['name']; $parentId = $customer['parentID']; $calls = $customer['calls']; $type = $customer['type']; $duration = $customer['duration']; //if id/type is insered yet if(array_key_exists($id, $tempC) && array_key_exists($type, $tempC[$id])) { $tempC[$id]['calls'][$type] += $calls; $tempC[$id]['duration'][$type] += $duration; } else { //if subcustomer has calls of that type if(array_key_exists($customerId, $tempS) && array_key_exists($type, $tempS[$customerId])) { $tempC[$id]['calls'][$type] = $tempS[$id][$type] + $calls; $tempC[$id]['duration'][$type] = $tempS[$id][$type] + $duration; } else { $tempC[$id]['calls'][$type] = $calls; $tempC[$id]['duration'][$type] = $duration; } $tempC[$id]['name'] = $name; $tempC[$id]['parentID'] = $parentId; } } 

Имея эти два темп. массивов, мы должны вычислить массив результатов.

Вывод должен иметь такую ​​же структуру, как указано ниже:

 Array ( [0] => Array //indexes should be incremented, starting from 0 ( [name] => Telekom [label] => 01-02 //label = type [count] => 120 [mins] => 3400 [customerid] => 8 ) [1] => Array ( [name] => Telekom [label] => 080 [count] => 15 [mins] => 720 // mins = (duration / 60) [customerid] => 8 ) [2] => Array ( [name] => Telekom [label] => 05 [count] => 5 [mins] => 100 [customerid] => 8 ) [3] => Array ( [name] => Telekom [label] => 087 [count] => 15 [mins] => 200 [customerid] => 8 ) [4] => Array ( [name] => Orange [label] => 03 [count] => 150 [mins] => 4200 [customerid] => 16 ) [5] => Array ( [name] => Orange [label] => 04 [count] => 5 [mins] => 100 [customerid] => 16 ) .... ) 

Я пробовал:

 $result = array(); foreach($tempC as $id => $customer) { $type = key($customer['calls']); // ?? $calls = 0; $duration = 0; //sums calls of customer if(array_key_exists('calls', $customer) && array_key_exists($type, $customer['calls'])) { $calls += $customer['calls'][$type]; $duration += $customer['duration'][$type]; } //sums calls of subcustomer if(array_key_exists($id, $tempS) && array_key_exists($type, $tempS[$id])) { $calls += $tempS[$id][$type]['calls']; $duration += $tempS[$id][$type]['duration']; } //if there are calls, put in the result array if($calls>0) { $result[] = [ 'name' => $customer['name'], 'label' => $type, 'count' => $calls, 'mins' => ceil($duration/ 60), 'customerid' => $id ]; } } 

Но вышеприведенный код для получения окончательного массива результатов неверен где-то, потому что он не добавляет все вызовы и типы правильно.

Примечание: этот пост был создан с помощью пользователя @Lipsyor.

Вы можете собирать типы в массиве $types при создании временных массивов.

Прежде всего объявите массив:

 $types = array(); 

в каждом forach(...) для $customers и $subcustomers insert:

 $types[$type] = true; 

Обратите внимание, что я использую ключ массива для хранения имени типа: используя этот трюк, вы никогда не вставляете дубликаты в массив.

Здесь код для создания массива результатов:

 $result = array(); foreach($tempC as $id => $customer) { foreach ($types as $type => $value) { $call = 0; $duration = 0; if(array_key_exists('calls', $customer) && array_key_exists($type, $customer['calls'])) { $call += $customer['calls'][$type]; $duration += $customer['duration'][$type]; } if(array_key_exists($id, $tempS) && array_key_exists($type, $tempS[$id])) { $call += $tempS[$id][$type]['calls']; $duration += $tempS[$id][$type]['duration']; } if($call>0) { $result[] = [ 'name' => $customer['name'], 'label' => $type, 'count' => $call, 'mins' => ceil($duration / 60), 'customerid' => $id ]; } } }