Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5. На примерах. Авторы: Кузнецов М.В., Симдянов И.В., Голышев С.В. Самоучитель MySQL 5. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Помогите с запросом к дереву вложенных каталогов
 
 автор: Гость   (10.10.2009 в 19:37)   письмо автору
 
 

Есть таблица вида id | id_deep | name . В ней перечень категорий, с некой степенью вложенности в друг друга (id_deep, если равна нулю - то верхний уровень, иначе это подуровень категории с данным id, причем категории с разным id_deep могут иметь одинаковые значения name).Т.е

Автомобиль (id = 1, id_deep=0)
--- Отечественный (id=2, id_deep=1)
------Ока (id =3, id_deep =2)
--- Зарубежный (id=4, id_deep = 1)

И мы получаем три переменные ($name1, $name2, $name3). Которые содержат name из таблицы. Причем переменная 1 содержит имя верхней категории, 2 - второй и т.д.

Предположим переменные выглядят как
$name1 = Автомобиль
$name2 = Отечественный
$name3 = Ока

Нам нужно получить id Оки. В данный момент я для этого делаю три запроса - сначала выбираю по $name1, где id_deep = 0, потом по $name2 где id_deep равен полученному id от $name1 и аналогично получаю необходимый id оки. В связи с чем вопрос - можно ли как-то уместить все эти три запроса к бд в один?

  Ответить  
 
 автор: cheops   (10.10.2009 в 19:49)   письмо автору
 
   для: Гость   (10.10.2009 в 19:37)
 

Что-то не очень понятно, а как id = 2, отличаете от id = 4 - у них у обоих id_deep = 1. Какая изначальная задача, что проектируете?

Вообще если не нравится последовательный вызов - обычно таблицу каталогов извлекают в оперативную память в виде массива и тогда все запросы - это дешевые обращения к массиву (вместо дорогих обращений к базе данных).

  Ответить  
 
 автор: Гость   (10.10.2009 в 20:10)   письмо автору
 
   для: cheops   (10.10.2009 в 19:49)
 

id_deep = 1 указывает что они вложенны в каталог с id = 1. То есть в одном каталоге может быть много подкаталогов.

Проектируется что-то вроде каталога, содержащего товары, по категориям, подкатегориям, подподкатегориям (и т.д. с неограниченной вложенностью). Причем есть четкая установка использовать урл вида site/catalog/вид_товара/подвид_товара/т.д./товар.

  Ответить  
 
 автор: cheops   (10.10.2009 в 20:19)   письмо автору
 
   для: Гость   (10.10.2009 в 20:10)
 

Так для чего потребовался "id Оки"? и только ли его вы хоите получить, может это все-таки группа записей входящих в подкаталог Отчечественный? Или вам наоборот по "id Оки" нужно восстановить навигационную цепочку к корневому каталогу? Просто без дополнительной информации "id Оки" получить невозможно, так как этот идентфикатор не отличается от остальных в этом же каталоге и непонятно какой критерий следует использовать для того, чтобы отличить эту запись от соседней, которых может быть больше, чем одна.

  Ответить  
 
 автор: Гость   (10.10.2009 в 20:38)   письмо автору
 
   для: cheops   (10.10.2009 в 20:19)
 

Ну нужно получить не только id а и другие столбцы, которые в данном решении неважны - типа описания, фото, даты и т.п.

Единственный способ получить id оки это тот что я описал.
мы получаем урл вида catalog/Автомобиль/Отечественный/Ока

Самое простое было бы сделать - SELECT * WHERE name = `Ока`, но поскольку записей с именем "ока" можетоказаться несколько, то прхиодится идти по началу.
Поскольку нам известно что первая переменная это "корень", то мы знаем что ее id_deep будет равен 0.
=> SELECT `id` WHERE name = Автомобиль AND id_deep = 0
Теперь получив этот id, мы ищем раздел "отечественный", id_deep которого для раздела автомобили будет равна полученному только что id.
=> SELECT `id` WHERE name = отечественный AND id_deep = id_раздела_автомобиль_у_которого_id_deep=0
получив этот id мы уже точно знаем что id_deep у Оки будет равно только что полученному id.

Тоесть по сути мне нужно понять - можно ли построить запрос вида
SELECT `id` WHERE name = отечественный AND id_deep = id_раздела_автомобиль_у_которого_id_deep=0

  Ответить  
 
 автор: cheops   (10.10.2009 в 21:10)   письмо автору
 
   для: Гость   (10.10.2009 в 20:38)
 

Погодите, а как вы получаете URL вида "catalog/Автомобиль/Отечественный/Ока", не при помощи mod_rewrite? Или у вас все эти каталоги существуют физически на жестком диске? Просто выглядит немного фантастично - у вас имеется база данных со всеми данными, у вас формируется путь - а для извлечения данных, которые были известны на момент генерации страницы приходится разворачивать весь путь, причем с использованием дорогих строковых условий?

  Ответить  
 
 автор: Гость   (10.10.2009 в 21:55)   письмо автору
 
   для: cheops   (10.10.2009 в 21:10)
 

Путь фактически генерируется как раз mod_rewrite. Из него и получаем $nameX. (если вдаваться в подробности, то это просто управление роутами в ZF)

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

Я так понял что это одним запросом сделать не удастся?

  Ответить  
 
 автор: serjinio   (11.10.2009 в 01:36)   письмо автору
 
   для: Гость   (10.10.2009 в 21:55)
 

FROM `table`  `t1` 
JOIN `table`  `t2` ON  `t2`.`id_deep` = `t1`.`id`
JOIN `table`  `t3` ON  `t3`.`id_deep` = `t2`.`id`
WHERE `t1`.`name`='$name2' 
AND   `t2`.`name`='$name1'
AND   `t3`.`name`='$name3'

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования