Как сделать MySQL Looped Join, какие тесты, если результаты полны?

0

Ситуация:
У меня есть таблица каталогов mysql. Каждый каталог имеет родительский каталог (хранится как parentID), вплоть до того момента, когда корневой каталог имеет parentID 0.

например:.

rowID: 1, name: Dir1,    parentID: 0 (root directory)
rowID: 2, name: Dir2,    parentID: 0 (root directory)
rowID: 3, name: Subdir1, parentID: 1 (lives in "Dir1")
rowID: 4, name: Subdir2, parentID: 1 (lives in "Dir1")
rowID: 5, name: Subdir3, parentID: 3 (lives in "Subdir1", which in turn lives in "Dir1")
rowID: 6, name: Subdir4, parentID: 5 (lives in "Subdir3", which lives in "Subdir1", which lives in "Dir1")

Итак, здесь есть 3 структуры глубины каталога.

Мне нужно создать оператор, который присоединяет любой каталог к ​​его родительскому объекту и продолжает делать это до тех пор, пока последний объединенный каталог не будет иметь parentID из 0 (т.е. нашел корневой каталог). Вы можете думать об этом так, как будто, учитывая любой каталог, вы можете найти корневую папку обратно родительскому.

Я полагаю, что для этого может потребоваться некоторый цикл MySQL, но для жизни я не могу заставить ни один из веб-примеров работать. Я даже не могу получить некоторые примеры для запуска, поскольку в них, похоже, есть какие-то синтаксические ошибки. Может кто-нибудь помочь мне начать?

Я могу принять любой формат результата, который является самым простым и дает лучшую производительность, чтобы сделать это. Либо простой массив номеров строк в правильном порядке (например, 5, 3, 1, 0, указывающий шаги для получения идентификатора 0), либо полную таблицу (лучше всего), которая будет упорядоченным списком строк, которые достигают этого, например,

rowID: 5, name: Subdir3, parentID: 2;
rowID: 3, name: Subdir1, parentID: 1;
rowId: 1, name: Dir1,    parentID: 0;

Помогите оценить!

Теги:
loops
join

2 ответа

0

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

Таблица выглядит следующим образом:

CREATE TABLE `t_hierarchy` (
    `rowID` INT(11) NULL DEFAULT NULL,
    `name` VARCHAR(50) NULL DEFAULT NULL COLLATE 'latin1_general_ci',
    `parentID` INT(11) NULL DEFAULT NULL
);

Я в основном вставлял то же самое, что и выше, но использовал значения NULL вместо 0 для root/no parent

То, что я сделал, является довольно загадочным примером из http://explainextended.com/2009/07/20/hierarchical-data-in-mysql-parents-and-children-in-one-query/.  и просто скорректировал имена столбцов, чтобы они соответствовали моим.

Поскольку это только порождает рекурсивную иерархию, я просто добавил глупое соединение в пример (ad.rowID = qi.id):

 SELECT  qi.id, qi.parent, ad.rowId, ad.name, level
FROM    (
        SELECT  @r AS id,
                (
                SELECT  @r := parentID
                FROM    t_hierarchy
                WHERE   rowID = id
                ) AS parent,
                @l := @l + 1 AS level
        FROM    (
                SELECT  @r := 5, -- change this 5 to the directory ID you want to resolve
                        @l := 0,
                        @cl := 0
                ) vars,
                t_hierarchy h
        WHERE   @r <> 0
        ORDER BY
                level DESC
        ) qi, t_hierarchy ad
        WHERE ad.rowID = qi.id

И это генерирует следующий (желаемый) вывод:

id parent rowId уровень имени

1 NULL 1 Dir1 3

3 1 3 Subdir1 2

5 3 5 Subdir3 1

Уровень - это вспомогательный столбец, который говорит вам, как "глубоко" он должен был решить, чтобы достичь этого. Все, что вам нужно сделать, это изменить "5" рядом с @r: = на идентификатор каталога, из которого вы хотите продолжить итерацию.

Если вы хотите переключить направление (от до нисходящего), просто отсортируйте по столбцу уровня ([...] WHERE ad.rowID = qi.id ORDER BY level ASC)

Надеюсь, это поможет вам.

Изменить: qi.id и ad.rowID являются дубликатами, просто удалите один из них; -)... черт возьми, я ненавижу этот материал иерархии

  • 0
    Спасибо вам большое! Я думаю, что заставил это работать ... только я тогда еще немного спросил, и очевидно, что производительность потенциально опасно плоха. Если, скажем, данные mysql изменяются на полпути через итерацию, это вызовет некоторые неприятные ошибки. Мне, возможно, придется просто использовать php, чтобы пройти через него, кажется, и ограничить глубину чем-то осмысленным, чтобы он не ошибался и не зависал. Вы бы сказали то же самое о производительности такого рода суперзапроса?
  • 0
    Да, такой вид всегда плох. Вы всегда можете положить «древовидную» структуру в текстовый столбец, как в обычной ОС (/ dir1 / subdir1 / subdir5), а затем извлечь необходимую информацию через PHP ... наверняка будет быстрее.
Показать ещё 1 комментарий
0

Ну, может быть, вы не нашли хороший веб-пример, потому что вы использовали неправильный поисковый термин. Описанная проблема отлично вписывается в оракулы CONNECT BY PRIOR и при поиске по mysql-эквивалентам этого утверждения вы находите http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/ довольно быстро.

Поскольку это не так просто (и у меня нет mysql-db, чтобы изнасиловать здесь), чтобы написать этот материал, просто взгляните на приведенные хорошие примеры (вы даже можете сделать это без развернутых функций через http://explainextended.com/2009/07/20/hierarchical-data-in-mysql-parents-and-children-in-one-query/.

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

  • 0
    Спасибо Найзеро за разъяснения. Очевидно, я думал о неправильных терминах для поиска. Мне удалось заставить родительский hiearchical запрос работать нормально, но я, похоже, не смог заставить его работать. Я попробовал заявление, которое они дали, но нет кода для объявленной функции (вторая ссылка). Я попытался подключить функцию из первой ссылки, но в строке 5 также произошла ошибка, в которой были объявлены переменные. Я делаю что-то совершенно не так? Извините за потенциально глупый вопрос. Я знаком с простыми запросами MySQL, но это выходит за рамки моей компетенции. Благодарю.
  • 0
    Кроме того, есть ли у вас представление о производительности довольно сложных запросов, подобных этому?
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню