Создать дерево с условием?

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

Предположим есть следующая структура в таблице БД.
Users
1.id
2.name
3.affiliated_by

Как я это вижу - необходимо взять из базы первую запись с идентификатором авторизованного пользователя и использовать его для проверки, есть ли в базе запись, где affiliated_id будет равна идентификатору текущего пользователя.

Если запись найдена, то мы берем идентификатор этой записи и снова проверяем, существует ли записи, где affiliated_id будет равна предыдущей записи. Соответственно таким образом я получу корректную цепочку пользователей. Укажите на мои и шибки и правильный путь для решения задачи, если можно с примерами, буду крайне признателен. Спасибо!

$users = [
            0 => ['id' => 1, 'name' => 'Name', 'affiliated_by' => null],
            1 => ['id' => 2, 'name' => 'Name', 'affiliated_by' => 1],
            2 => ['id' => 3, 'name' => 'Name', 'affiliated_by' => 1],
            3 => ['id' => 4, 'name' => 'Name', 'affiliated_by' => 2],
            4 => ['id' => 5, 'name' => 'Name', 'affiliated_by' => 3],
            5 => ['id' => 6, 'name' => 'Name', 'affiliated_by' => null],
            6 => ['id' => 7, 'name' => 'Name', 'affiliated_by' => null],
            7 => ['id' => 8, 'name' => 'Name', 'affiliated_by' => 7],
        ];

        $refs = [];
        $uid = 1;

        foreach($users as $user)
        {
            if ($user['id'] == next($users)['affiliated_by'])
                $refs[] = $user;
        }


На выходе, хотелось бы получить следующий массив

$refs = [
            0 => ['id' => 2, 'name' => 'Name', 'affiliated_by' => 1],
            1 => ['id' => 3, 'name' => 'Name', 'affiliated_by' => 1],
            2 => ['id' => 4, 'name' => 'Name', 'affiliated_by' => 3],
            3 => ['id' => 5, 'name' => 'Name', 'affiliated_by' => 4],
        ];
  • Вопрос задан
  • 116 просмотров
Решения вопроса 1
Immortal_pony
@Immortal_pony Куратор тега PHP
Уверен, что задача простая, но я никак не соображу.

Абсолютно напрасно, задачи с деревьями довольно сложны.

Предположим есть следующая структура в таблице БД.
Users
1.id
2.name
3.affiliated_by

Это неподходящая структура для хранения деревьев.
Пост на хабре, в котором описаны различные варианты хранения деревьев в БД. Там и запросы указаны, которым эти данные можно легко и быстро получить.

Для вашей структуры придется вытащить всех пользователей из БД и потом вручную с помощью рекурсии построить цепочку. Примерно так:
function buildAffiliateChain($for, $users) {
    $chain = [];
    
    $affiliatedUsers = array_values(array_filter($users, function($user) use ($for) {
        return $user['affiliated_by'] === $for;
    }));
    
    foreach ($affiliatedUsers as $affiliatedUser) {
        $subscequentChain = buildAffiliateChain($affiliatedUser['id'], $users);
        $chain = array_merge($chain, [$affiliatedUser], $subscequentChain);
    }
    
    usort($chain, function($someUser, $otherUser) { 
        return $someUser['affiliated_by'] > $otherUser['affiliated_by'] ? 1 : -1;
    });
    
    return $chain;
}


Если количество пользователей будет измеряться тысячами, то подобный алгоритм будет крайне неэффективен. На малых объемах проблем не будет.

PS Рекурсию можно использовать и в поcледних версиях MySQL, так что аналогичным способом можно решить вопрос и на уровне БД. Однако производительность от этого не вырастест.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
IceRD
@IceRD
Может брать сразу необходимые, отсортированные данные?
SELECT id, name, affiliated_by FROM Users WHERE affiliated_by !=null ORDER BY affiliated_by
Ответ написан
@heartdevil
плыву как воздушный шарик
Точно не могу проверить, но попробуйте такого вида запрос
SELECT u.id, u.name, u.affiliated_by FROM Users AS u 
LEFT JOIN Users AS u2 On u.id = u2.affiliated_by
ORDER BY u2.affiliated_by

(надо будет подстроить INNER/LEFT ну и сортировку)
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы