Иерархическое хранилище MySQL: поиск по всем родителям / бабушкам и т. Д. узлам задан идентификатор дочернего узла?

Я храню категории с использованием иерархической модели:

CATEGORIES id | parent_id | name --------------------- 1 | 0 | Cars 2 | 0 | Planes 3 | 1 | Hatchbacks 4 | 1 | Convertibles 5 | 2 | Jets 6 | 3 | Peugeot 7 | 3 | BMW 8 | 6 | 206 9 | 6 | 306 

Затем я сохраняю фактические данные с одним из этих идентификаторов категории следующим образом:

 CARS vehicle_id | category_id | name ------------------------------- 1 | 8 | Really fast silver Peugeot 206 2 | 9 | Really fast silver Peugeot 306 3 | 5 | Really fast Boeing 747 4 | 3 | Another Peugeot but only in Hatchbacks category 

При поиске любой из этих данных я хотел бы найти всех дочерних / внуков / внуков и т. Д. Узлов. Поэтому, если кто-то хочет увидеть все «Автомобили», они видят все с помощью parent_id «Hatchbacks», а значит, все с parent_id «Peugeot» и т. Д. На произвольный уровень.

Поэтому, если я перечислил «действительно быстрый Peugeot 206» с category_id из 1, 3, 6 или 8, мой запрос должен иметь возможность «путешествовать» по дереву и находить более высокие категории, которые являются родителями / бабушками и дедушками этого ребенка категория. Например, пользователь, ищущий Peugeots в категории «8», должен найти любые Peugeot, перечисленные в категориях 6, 3 или 1, – все из потомков категории 8.

Например, используя приведенные выше данные, поиск «Peugeot» в категории 3 должен действительно находить автомобили 1, 2 и 4, потому что транспортные средства 1 и 2 имеют предковую дорожку категории, которая ведет обратно в категорию 3. См.?

Извините, если я не объяснил это хорошо. Это трудно! Однако, спасибо.

Примечание. Я прочитал статью MySQL dev по иерархиям .

Нормализованные модели великолепны, но не тогда, когда вы действительно должны их запрашивать.

Просто сохраните «путь» к вашей категории в таблице категорий. Например: path = / 1/3/4 и когда вы запрашиваете такую ​​базу данных, как «выберите … где путь, как« / 1/3 /% », это будет намного проще и быстрее, чем несколько иерархических запросов …

Мне нравится объяснение, предоставленное SitePoint. Он дает вам код и объясняет теорию, лежащую в ее основе.

http://blogs.sitepoint.com/hierarchical-data-database/

Примечание: этот метод лучше для чтения, чем для записи. Если вы постоянно пишете дерево, я бы использовал другой алгоритм. Этот метод оптимизирован для чтения (поиска).

Вы представляете свои данные в виде модели списка адресов, чьи запросы в MySQL лучше всего использовать с использованием переменных сеанса . Теперь это не единственный способ представить иерархию в реляционной базе данных . Для вашей конкретной проблемы я, скорее всего, использовал бы материализованный подход к пути , где вы покончили бы с фактической таблицей категорий, а вместо этого столбец на вашей таблице автомобилей, который выглядит как Cars/Hatchbacks/Peugeot на основе записи и использует LIKE запросы , К сожалению, это было бы медленным, так как количество записей увеличивалось. Теперь, если вы знаете максимальную глубину своей иерархии (например, четыре уровня), вы можете разбить ее на отдельные столбцы, что позволяет вам использовать индексирование.