Подсчет количества зависимых пользователей в стркутуре

bisworld

Новичок
Здравствуйте, такая проблема:

Есть таблица в MySQL, полей много, но нужные для решения задачи id и parent_id. (id - идентификатор инкрементный, parent_id - соответственно id родителя).

Что собственно требуется:

Требуется организовать принцип сети (как в сетевом маркетинге), то-есть подсчитать количество пользователей (для любого пользователя) на каждом уровне вложенности. (уровень вложенности не ограничен, но желательно иметь возможность ограничивать уровень вложенности). Саму структуру выводите не нужно, только подсчет. Желательно вывод результата массивом типа:

$counter(
1 => 25; // на первом уровне 25
2 => 37; // на втором уровне 37
3 = > 57; .. и т.д
4 => 49:
... и т.д.
)
 

bisworld

Новичок
Я уже давно приступил, пока ничего толкового, гугл тоже что то не особо помогает, везде только вывод структуры, а подсчета никто не делает
 

Фанат

oncle terrible
Команда форума
Я уже давно приступил, пока ничего толкового
Ничего страшного.
Не отчаивайся.
Не всякая проблема даётся сразу - бывает, приходится над ней попотеть и день, и два, и неделю.
Главное - не теряй веру в себя и не прекращай усилий.
 

~WR~

Новичок
Самое первое, что приходит в голову - использовать Materialized path.
Добавляем колонку, в которой будет храниться полный "путь" в дереве для этого юзера.

PHP:
id | parent_id | path
1  | NULL      | 1       
2  | 1         | 1.2
3  | 2         | 1.2.3 
4  | 1         | 1.4
Уровень каждого пользователя легко узнать, посчитав количество разделителей в path (в данном случае - точек). И далее GROUP BY + count(*). Всё просто. :)

В этой схеме также легко можно найти такие вещи, как "все потомки пользователя до самого конца дерева". В один проход и без join'ов.
Здесь есть еще куча интереснейших вещей, но многое, к сожалению, упрется в ущербность mysql.
 

bisworld

Новичок
PHP:
public function getUserSeti()
	  {
		  global $db;
		  
		  $sql = "SELECT id, parent_id "
			  . "\n FROM " . $this->uTable
			  . "\n WHERE id > '" . $this->uid . "'"
			  . "\n ORDER BY parent_id";
		  
		  $row = $db->fetch_all($sql);

		  return ($row) ? $row : 0;
	  }
	  
	  public function getSeti($array, $parent_id = 0, $k = 0)
	  {
		  global $db;
		  
		  $count = Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
		  
		  foreach($array as $row) {
			  if($row['parent_id'] == $parent_id) {
				  
				   $count[$k]++;
				   
				   $count_last = $this->getSeti($array, $row['id'], $k + 1);
				   
				   foreach($count as $key => $val) {
					   $count[$key] += $count_last[$key];
				   }
			  }
		  }

		  return $count;
	  }



$seti    = $user->getUserSeti();
$setirow = $user->getSeti($seti, $user->uid);
<table class="cartTable">
<thead>
<tr>
<th>Уровень</th>
<th style="text-align:center;">Кол-во партнеров</th>
</tr>
</thead>
<?php if(!$setirow):?>
<tbody>
<tr>
<td colspan="2"><?php echo $core->msgAlert("<span>Оповещение!</span>У Вас еще нет ни одного партнера...", false);?></td>
</tr>
</tbody>
<?php else:
$i = 0;
foreach ($setirow as $srow):
?>
<tbody>
<tr>
<td><?php echo ++$i;?> Уровень</td>
<td style="text-align:center"><?php echo $srow;?></td>
</tr>
<?php endforeach;?>
</tbody>
<?php unset($srow);?>
<?php endif;?>
</table>


Долго мучался, получилось, как то так. Код полностью рабочий, может не сильно оптимальный, но главное свою задачу решает
 
Сверху