SQL - рекурсивный запрос или ...?

*
1
*
✩ 2
Делаю магазин.
В ТЗ есть требование - не ограниченная вложенность разделов.

Все разделы хранятся в одной таблице
id
title
parent

Как получить все подразделы данного раздела не прибегая к рекурсии?
Может есть какие-то другие методы работы с деревом?
Пните в нужную сторону, плиз.
sql рекурсия
1 месяц 14 дней назад
#ссылка не по теме? tweet
А чем не нравится рекурсия? – zhukov.roman 1 месяц 14 дней назад
При увеличении количества вложенных категорий растет количество запросов к базе данных (+1 вложенная категория = +1 запрос). В найденном мной решении достаточно одного запроса при любом количестве категорий и любой глубине вложенности. В качестве расплаты - небольшое усложнение алгоритма управления категориями. – dreamComeTrue 1 месяц 14 дней назад
>В найденном мной решении ... может поделитесь? – bodnar 1 месяц 14 дней назад
Чуть ниже помечен правильный ответ :) – dreamComeTrue 1 месяц 14 дней назад
комментировать



*
1
*
Нашел исчерпывающий ответ
#ссылка не по теме?
1 месяц 14 дней назад
а еще можно изначально все сделать вложенными множествами http://www.getinfo.ru/article610.html если не меняя структуры бд, то без рекурсивной функции/хранимки не обойтись. Обычно такие задачи решаются дизайном - подгрузка только нескольких уровней, а остальные уже по требованию (что-то вроде lazy loading) – mihasic 1 месяц 14 дней назад
Nested sets не понравился мне тем, что при добавлении листа приходится изменять все элементы дерева, которые будут правее добавленного. В остальном, для моего случая, Nested sets всем хорош – dreamComeTrue 1 месяц 14 дней назад
Комментировать
*
0
*
Пните в нужную сторону, плиз.


Cписки смежности?

Вариант в 2 запроса с извращением на PHP.
select count(distinct c.id) as `maxdeep` from table c inner join table p on c.id = p.parent
// это как бы будет максимальный уровень вложенности


// затем понадобится два цикла: for(i = maxdeep; i >= 1; i--) для создания всего пути
concat_ws(' > ', p(n).name, ..., pp.name,p.name, c.name) as path
// еще можно добавить id-шники, если нужно что-то типа ссылок
concat_ws(' > ', p(n).id, ..., pp.id,p.id, c.id) as treeid

// второй цикл for(i = 1; $i < maxdeep; i++) для соеденения таблиц с собой
// если есть какой-нибудь класс SqlBuilder, то вообще все элегантно смотрится

// в итоге должно получиться что-то вроде
SELECT c.* , concat_ws(' > ', p(n).name, ..., pp.name,p.name, c.name) as path
FROM category c
LEFT JOIN Category p on p.id = c.parent
LEFT JOIN Category pp on pp.id = p.parent
...
LEFT JOIN Category p(n) on p(n).id = p(n-1).parent
// здесь p(n) - алиас , выглядит для n = 4 так pppp, для n = 5 ppppp и т.д.

Выполняем этот запрос (это выбор всего дерева), в результате получится что-то вроде
id  parent name      path
1    0    Root1    Root1
2   0   Root2   Root2
3   1   Child1   Root1 > Child1
4   3   Child1Child3   Root1 > Child1 > Child1Child3

если был treeid, то будет аналогичная петрушка path только из id (1 > 3 > 4)

Осталось распарсить и сопоставить строки path и treeid (если нужно).

Насчет неограниченной вложенности, по моему в старых версиях mysql было какое-то ограничение на соеденение (left join) (30, если не ошибаюсь). В новых по-моему нет.
#ссылка не по теме?
1 месяц 14 дней назад

Комментировать

Ваш Ответ:



Ваш OpenID



Получить OpenID

Что такое OpenID?
или

Логин

Email

Пароль


Будет создана учетная запись и на email выслано письмо подтверждения.


новые ответы

Первый раз на сайте?

askdev.ru — это социальный сайт вопросов и ответов для IT-специалистов: программистов, веб-дизайнеров, системных администраторов.
о сайте » регистрация »

Показан

272 раза

Задан

1 месяц 14 дней назад

Теги

sql x 29
рекурсия x 2
X

Пожалуйста, войдите:


Имя:
Пароль:
регистрация
Или используйте OpenID