PHP: сортировка данных из вложенных наборов

В настоящее время мы создаем веб-сайт с категоризированной таблицей MySQL, содержащей различные компетенции, и мы заметили, что модель вложенного набора будет оптимизирована для этого. Хотя у нас есть довольно серьезная проблема — модель вложенного набора не позволяет никакой сортировки, а нам очень нужна такая возможность. Я бы хотел, чтобы выходные данные были массивом (идентификатор, имя, глубина), поскольку эта функция поддерживает (хотя и без какой-либо сортировки):

function tree()
{
    $query = 'SELECT node.id, node.name, (COUNT(parent.name) - 1) AS depth FROM test_competence AS node, test_competence AS parent WHERE node.lft BETWEEN parent.lft AND parent.rgt GROUP BY node.name ORDER BY node.lft';
    $result = mysql_query($query) or die(mysql_error());

    while($data = mysql_fetch_assoc($result))
    {
        $returnarray[] = $data;
    }

    return $returnarray;
}

Я начал с функции, но понятия не имею, как продолжить:

function tree_sorted()
{
    //Get data
    $query = 'SELECT node.id, node.name, node.parent, (COUNT(parent.name) - 1) AS depth FROM test_competence AS node, test_competence AS parent WHERE node.lft BETWEEN parent.lft AND parent.rgt GROUP BY node.name ORDER BY node.lft';
    $result = mysql_query($query) or die(mysql_error());

    //Fetch gotten data
    while($data = mysql_fetch_assoc($result))
    {
        $fetched[$data['depth']][$data['id']] = array($data['name'], $data['parent']);
    }

    //Sort fetched data
    foreach($fetched as $i => $row)
    {
        asort($row);
        $sorted[$i] = $row;
    }

    //Merge sorted data (???)
    foreach($sorted as $i => $arr)
    {
        foreach($arr as $x => $row)
        {
            $returnarray[] = array('id' => key($row), 'name' => $row[0], 'depth' => $x);
        }
    }

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

Заранее спасибо.

РЕДАКТИРОВАТЬ: теперь я попробовал некоторые функции с функцией uasort(), которая кажется правильной, но проблема все еще остается.


person Ivar    schedule 16.05.2009    source источник
comment
В качестве второстепенного момента я бы рекомендовал явное JOIN в вашем SQL, а не неявное.   -  person staticsan    schedule 18.05.2009


Ответы (3)


Если вам нужно отсортировать набор узлов в дереве и поддерживать неограниченное количество уровней в дереве, могу ли я порекомендовать использовать предварительно упорядоченный обход дерева?

См. http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/ для примера реализации.

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

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

person Alistair Evans    schedule 02.06.2009

По моему опыту, использование модели вложенных наборов на самом деле не обязательно, если вы не ожидаете действительно интенсивного трафика. Я не уверен, для чего именно вам нужна иерархия, но я бы рекомендовал проверить, не будет ли достаточно простой таблицы parent-son-table с кешем перед ней, ее намного проще поддерживать и работать с

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

person n3rd    schedule 16.05.2009
comment
В нашем случае важна не только производительность. Модель вложенных множеств поддерживает неограниченные уровни категорий по сравнению с общей родительской техникой, которая ограничивает количество уровней в запросе (каждый уровень требует левого соединения, и в нашем случае количество уровней может сильно различаться в каждой компетенции). - person Ivar; 16.05.2009

Принимая удар в темноте, поскольку данные вложенного дерева наборов по определению уже отсортированы, похоже, что вам нужно преобразовать данные в другой формат (обычно плоский), чтобы отсортировать их. Самый простой способ добиться этого — просто работать с данными, создавая плоский набор данных по мере продвижения.

У вас уже есть несколько вариантов в SQL. Упорядочивание по левому идентификатору обеспечивает обход по порядку, если я правильно понимаю терминологию. Обычно это то, что люди хотят, когда они перечисляют дерево наборов, поскольку это имеет смысл, когда он сводится к списку. Я бы поэкспериментировал с предложением ORDER BY в SQL; например, упорядочение по параметру глубины даст вам обход по уровням. Попробуйте совместить это с node.name.

person staticsan    schedule 18.05.2009