Mysql рекурсия?

Рассмотрим такую ​​таблицу:

   folders_table
   -----------------------
      INT id_folder
      INT id_folder_parent
      VARCHAR folder_name

Который хранит простую структуру каталогов. Как я могу получить все подкаталоги каталога с помощью одного запроса SELECT?

5 ответов

Решение

Это возможно, но вам нужно изменить структуру базы данных; После внесения изменений вы можете получить дерево любой глубины за один запрос. Запросы немного сложнее, но все же довольно просто.

С показанной выше структурой таблицы это невозможно сделать с MySQL, поскольку он не поддерживает рекурсивные запросы.

Другой вариант - сохранить глубину узла и сохранить идентификатор для полного пути каждого узла и использовать оба из них в качестве критериев.

Я храню узлы XML в реляционной базе данных следующим образом:

SELECT id,value FROM element e1
INNER JOIN element e2 ON (e2.id=e1.parent_id AND name='friend')
WHERE e1.depth>4 AND e1.path like 'root[1]/users[1]/user:dana[1]/public[1]%'

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

Когда вы вставляете каждый узел, вы должны рассчитать полный путь, следуя за родителями до корневого узла (parent_id IS NULL) добавляя каждый уровень в массив, одновременно сохраняя глубину пути.

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

Левая / правая схема хранения узлов в иерархии (список смежных вложенных множеств) слишком опасна для меня, и гораздо больше может пойти не так с такой схемой, для которой очень сложно управлять.

1、 создать новую таблицу. tree_folder(id, id_folder, tree_id)2 、 создать новую таблицу. tree(id, tree_json)

tree Таблица поддерживает весь узел дерева. Например, следующее дерево с корневым узлом 1,

{
    "folder_id": 1,
    "parent_folder_id": 0,
    "children": [
      {
          "folder_id": 10,
          "parent_folder_id": 1,
          "children": null
      },
      {
          "folder_id": 11,
          "parent_folder_id": 2,
          "children": null
      }
    ]
}

Таблица содержит эту строку.

[id, tree_json]
[1, "xxxxx"]

Затем сохраните связь между узлом и деревом. Как видите, дерево содержит узел 1, 10, 11, Тогда у нас есть стол tree_folder,

[id, folder_id, tree_id]
[1,  1        ,  1]
[2,  10       , 1]
[3,  11       , 1]

Когда вам нужно получить папку 10дерево. просто достаньте из дерева, а затем разложите это в своей программе.

Таким образом, вы просто делаете рекурсию в памяти вместо mysql.

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

С MySql/MariaDB вы можете использовать движок Open Query Graph ( http://openquery.com/graph/doc), который представляет собой плагин mysql, который позволяет вам создать специальную таблицу, в которую вы помещаете отношения, в основном parentId и childId.

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

Он обрабатывает не только дерево (рекурсивные отношения 1-n), но и графические структуры данных (рекурсивные отношения nm) с весом (представьте, например, что вы хотите сохранить собственность компаний, у компании может быть несколько дочерних компаний, а также может быть несколько акционеров).

Другие вопросы по тегам