Mysql рекурсия?
Рассмотрим такую таблицу:
folders_table
-----------------------
INT id_folder
INT id_folder_parent
VARCHAR folder_name
Который хранит простую структуру каталогов. Как я могу получить все подкаталоги каталога с помощью одного запроса SELECT?
5 ответов
Это возможно, но вам нужно изменить структуру базы данных; После внесения изменений вы можете получить дерево любой глубины за один запрос. Запросы немного сложнее, но все же довольно просто.
- Хранение иерархических данных в базе данных (SitePoint) - эта статья шаг за шагом, очень понятна.
- Управление иерархическими данными в MySQL - не так ясно, как указано выше.
С показанной выше структурой таблицы это невозможно сделать с 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) с весом (представьте, например, что вы хотите сохранить собственность компаний, у компании может быть несколько дочерних компаний, а также может быть несколько акционеров).