Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: построение "хлебных крошек" одним запросом

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (2): [1] 2 »   

> Описание: все дерево в одной таблице
DlTA
Отправлено: 16 Декабря, 2011 - 13:55:13
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2952
Дата рег-ции: Окт. 2010  


Помог: 53 раз(а)




допустим имеем табличку
`каталог`
`ид` | `название` | `родитель`

если родитель =0 то эти разделы в корне,
и на них ссылкются другие разделы

как получить "хлебные крошки" "ветвь дерева" одним запросом?
запрос:
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT * FROM `каталог`, `каталог` AS `предок` WHERE
  2. `каталог`.`родитель` = `предок`.`ид`
даст ссылку только на родительский раздел
а хотелось бы всю ветвь до корня и одним запросом.
 
 Top
OrmaJever
Отправлено: 16 Декабря, 2011 - 14:06:30
Post Id



Активный участник


Покинул форум
Сообщений всего: 7540
Дата рег-ции: Янв. 2010  
Откуда: Чернигов


Помог: 299 раз(а)




рекурсия


-----
Если вы хотя бы 3-4 раза не решите всё выкинуть и начать заново - вы явно что-то делаете не так.
 
 Top
tuareg
Отправлено: 16 Декабря, 2011 - 14:09:56
Post Id


Участник


Покинул форум
Сообщений всего: 1234
Дата рег-ции: Июнь 2010  


Помог: 69 раз(а)




Если у Вас неограниченное количество вложений, то в данном варианте никак.
Если знаете сколько вложений то нужно связать столько таблиц сколько вложений.

(Отредактировано автором: 16 Декабря, 2011 - 14:11:19)

 
 Top
EuGen Администратор
Отправлено: 16 Декабря, 2011 - 14:10:02
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Самое простое в такой ситуации - хранить отдельно полный путь (в упорядоченном виде) для каждого элемента в отдельном поле. Имеет свои минусы - при изменении структуры нужно перестраивать.

Иным решением станет хранение дополнительно позиции. Здесь пример:

http://stackoverflow[dot]com/questio[dot][dot][dot]-for-nested-sets


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
DlTA
Отправлено: 16 Декабря, 2011 - 16:41:11
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2952
Дата рег-ции: Окт. 2010  


Помог: 53 раз(а)




OrmaJever пишет:
рекурсия
это каждый раз новый запрос, не катит

tuareg пишет:
Если знаете сколько вложений то нужно связать столько таблиц сколько вложений.
а это все равно как минимум 2 запроса.

EuGen пишет:
Иным решением станет хранение дополнительно позиции. Здесь пример:
http://stackoverflow.com/questio...-for-nested-sets

этот?
CODE (text):
скопировать код в буфер обмена
  1. ID   Name    ParentId  Left   Right   Path
  2. 0    Node A  0         1      12      0,
  3. 1    Node B  0         2      5       0,1,
  4. 2    Node C  1         3      4       0,1,2,
  5. 3    Node D  0         6      11      0,3,
  6. 4    Node E  3         7      8       0,3,4,
  7. 5    Node F  4         9      9       0,3,4,

CODE (SQL):
скопировать код в буфер обмена
  1. path = SELECT Path FROM Nodes WHERE ID = 3
  2. SELECT * FROM Nodes WHERE Path LIKE = path + '%'


а как работает это услови? WHERE Path LIKE = path + '%'
 
 Top
tuareg
Отправлено: 16 Декабря, 2011 - 18:47:58
Post Id


Участник


Покинул форум
Сообщений всего: 1234
Дата рег-ции: Июнь 2010  


Помог: 69 раз(а)




DlTA завтра если время будет посмотрю свой вариант.
По факту там только один запрос. Но надо знать сколько вложений
 
 Top
Champion Супермодератор
Отправлено: 16 Декабря, 2011 - 18:57:15
Post Id



Активный участник


Покинул форум
Сообщений всего: 4350
Дата рег-ции: Авг. 2008  
Откуда: Москва


Помог: 57 раз(а)




Если бы это был Postgres, Firebird, Oracle, MS SQL Server, то можно было бы вытянут рекурсивным запросом с WITH.

А поскольку речь, видимо о мускуле, то кроме предложенных вариантов еще вариант:
CODE (SQL):
скопировать код в буфер обмена
  1. SELECT t1.id, t2.id, t3.id, ....
  2. FROM tbl t1
  3. LEFT JOIN tbl t2 ON t2.id = t1.parent_id
  4. LEFT JOIN tbl t3 ON t3.id = t2.parent_id
  5. LEFT JOIN tbl t4 ON t4.id = t3.parent_id
  6. ....

Столько раз, сколько достаточно, чтоб покрыть максимально предполагаемую вложенность. Ну и проверку, дотянулись ли до корня и, если не дотянулись, то в этом редком случае второй запрос.
 
 Top
DlTA
Отправлено: 16 Декабря, 2011 - 19:13:15
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2952
Дата рег-ции: Окт. 2010  


Помог: 53 раз(а)




tuareg пишет:
По факту там только один запрос. Но надо знать сколько вложений
чтоб знать количество, его надо откуда то получить даже если это число хранить в той же таблице, это уже как минимум запрос,
зная количество конечно можно сгенерить многоуровневый селект, но интересовал более изящный вариант.
 
 Top
Champion Супермодератор
Отправлено: 16 Декабря, 2011 - 19:24:07
Post Id



Активный участник


Покинул форум
Сообщений всего: 4350
Дата рег-ции: Авг. 2008  
Откуда: Москва


Помог: 57 раз(а)




DlTA пишет:
чтоб знать количество, его надо откуда то получить
Можно получить слефтжойнить 50 раз - этого точно достаточно.
Мускуль сам поймет, что пора кончать джойнить, когда очередной join ничего не вернет.

DlTA пишет:
интересовал более изящный вариант.
EuGen пишет:
полный путь (в упорядоченном виде) для каждого элемента в отдельном поле.
 
 Top
DlTA
Отправлено: 16 Декабря, 2011 - 19:49:35
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2952
Дата рег-ции: Окт. 2010  


Помог: 53 раз(а)




Champion пишет:
SELECT t1.id, t2.id, t3.id, ....
FROM tbl t1
LEFT JOIN tbl t2 ON t2.id = t1.parent_id
LEFT JOIN tbl t3 ON t3.id = t2.parent_id

а это не сильно дофига длинная строка получается?
даже при 50 джоинах получится как минимум 100 ячеек на выходе (ид и название как минимум, и то фигня что почти все null-ом заполнены)
 
 Top
Champion Супермодератор
Отправлено: 16 Декабря, 2011 - 19:55:22
Post Id



Активный участник


Покинул форум
Сообщений всего: 4350
Дата рег-ции: Авг. 2008  
Откуда: Москва


Помог: 57 раз(а)




А что такого в том, что она длинная?)
Если набирать лень, то это можно сделать циклом. Если есть опасения, что мускуль такую длинную строку не съест, то нужно попробовать. Должен съесть.
(Добавление)
DlTA пишет:
и то фигня что почти все null-ом заполнены
Это разве делает какую-то проблему?
 
 Top
tuareg
Отправлено: 16 Декабря, 2011 - 20:34:46
Post Id


Участник


Покинул форум
Сообщений всего: 1234
Дата рег-ции: Июнь 2010  


Помог: 69 раз(а)




На Хабре по-моему чел сделал процедуру рекурсивную.
Я просто не могу понять в чем у Вас проблема, ну допустим будет запрос не один, ну и? его нельзя закэшировать? Если 2 запроса сделайте процедуру+ КЭШ
 
 Top
EuGen Администратор
Отправлено: 16 Декабря, 2011 - 20:38:33
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




И в чем разница? Рекурсивная процедура ничуть не лучше рекурсии на php.

50 JOIN - плохо, если данных действительно много. Изящества здесь уж точно нет.
То, что я предлагал с полным путем - вряд ли изящно тоже, так как в случае перемещения узла где-нибудь в середине пути будет очень много запросов на поиск и обновление (по сути обновить нужно будет все нижележащие поддеревья).

Изящно можно везде почти, кроме MySQL


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
tuareg
Отправлено: 17 Декабря, 2011 - 00:29:03
Post Id


Участник


Покинул форум
Сообщений всего: 1234
Дата рег-ции: Июнь 2010  


Помог: 69 раз(а)




Да не ну это глупо, зачем??? MySql не для этого
 
 Top
DlTA
Отправлено: 17 Декабря, 2011 - 01:07:24
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2952
Дата рег-ции: Окт. 2010  


Помог: 53 раз(а)




tuareg пишет:
Да не ну это глупо, зачем??? MySql не для этого

не для чего?
 
 Top
Страниц (2): [1] 2 »
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« SQL и Архитектура БД »


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



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB