Сложный SQL запрос
50 сообщений
#16 лет назад
Пожалуйста помогите сформировать запрос в MySQL.Имеем 2 таблицы:
Categories:
=========================
| ID | parent | name |
=========================
| 1 | NULL | Кино |
| 2 | NULL | Книги |
| 3 | NULL | Музыка |
| 4 | 1 | Комедия |
| 5 | 1 | Боевик |
| 6 | 1 | Драма |
| 7 | 2 | Роман |
| 8 | 2 | Комикс |
| 9 | 2 | Фэнтэзи |
| 10 | 3 | Дэнс |
| 11 | 3 | Рок |
| 12 | 3 | Поп |
=========================
Products:
=========================
| ID | catID | name |
=========================
| 1 | 4 | Комедия1|
| 2 | 4 | Комедия2|
| 3 | 5 | Боевик1 |
| 4 | 5 | Боевик2 |
| 5 | 6 | Драма1 |
| 6 | 6 | Драма2 |
| 7 | 7 | Роман1 |
| 8 | 7 | Роман2 |
| 9 | 8 | Комикс1 |
| 10 | 8 | Комикс2 |
| 11 | 11 | Рок1 |
| 12 | 11 | Рок2 |
=========================
Результатом должна быть таблица вида:
============================
| Name | catname | parent |
============================
Комедия1| Комедия | Кино |
Комедия2| Комедия | Кино |
Боевик1 | Боевик | Кино |
Боевик2 | Боевик | Кино |
Драма1 | Драма | Кино |
Драма2 | Драма | Кино |
Роман1 | Роман | Книги |
Роман2 | Роман | Книги |
Комикс1 | Комикс | Книги |
Комикс2 | Комикс | Книги |
Рок1 | Рок | Музыка |
Рок2 | Рок | Музыка |
============================
Вроде не сложно, но видимо у меня знаний не хватает, целый день мучаюсь никак не могу составить запрос.
50 сообщений
#16 лет назад
А ну супер, пока писал пост, появились новые мысли (на это я и расчитывал 
Запрос будет выглядеть так:
SELECT P.name AS Name, Cn.name AS catname, Cp.name AS parent
FROM Products P
INNER JOIN Categories Cn ON P.catID = Cn.ID
INNER JOIN Categories Cp ON Cn.ID = Cp.parent
Читаем:
Дайте мне названия всех продуктов и название их категорий и названия категорий их категорий (жесть)
ИЗ таблицы Products
ГДЕ ИД категории продукта равна категории1
ГДЕ ИД категории1 равна категории2 (тоесть родителю)
Кстати говоря если дерево глубже, как у меня на самом деле, то тупо добавляем
...
INNER JOIN Categories Cn ON P.catID = Cn.ID
INNER JOIN Categories Cp ON Cn.ID = Cp.parent
INNER JOIN Categories Cp1 ON Cp.parent = Cp1.parent
INNER JOIN Categories Cp2 ON Cp1.parent = Cp2.parent
И так до бесконечности
Всем спасибо

3195 сообщений
#16 лет назад
Я не очень в этом всём разбираюсь... но на мой взгляд со стороны... вы такими запросами сервак уроните...
83 сообщения
#16 лет назад
А получить эти данные одним запросом - так принципиально? Если использовать кеширование, то вариантов есть масса, и несколько (может даже один) дополнительных простых запроса на производительности отрицательно не повлияют

626 сообщений
#16 лет назад
Вряд ли у вас дерево категорий слишком большое. Вот и доставайте его 1 раз и храните в чем-нибудь хэшеобразном, где ключом будет поле ID. Я бы рекомендовал memcached, если хостинг позволяет - так вы это дерево будете использовать в течении многих запросов.
658 сообщений
#16 лет назад
Нужно из нормальной формы Бойса - Кодда довести до 4НФ.
1090 сообщений
#16 лет назад
Цитата ("sergannd_snz"):Нужно из нормальной формы Бойса - Кодда довести до 4НФ.
Не нужно. Нужно почитать про nested sets.
83 сообщения
#16 лет назад
unglued, я вам пример системы кеширования тут не приведу, можете найти сами, есть варианты сериализации, есть варианты кешировать ХТМЛ-вывод, для более сложных проектов - более сложные решения, типа мемкешедя лиш предложил идею - используя кеширования, можно особо не напрягаться с такими запросами, а делать несколько простых, результат выполнения сохранять в кеш, и пока кеш валидный, запросов к базе не будет
658 сообщений
#16 лет назад
Кривая структура бд. Почитайте про реляционную модель данных.
626 сообщений
#16 лет назад
Реляционная модель отнюдь не манна небесная. Объективная реальность диктует свои законы. Зачастую лучше внести в БД избыточность, чем делать лишние запросы, да еще с дикими JOIN-ами.
326 сообщений
#16 лет назад
SELECT p.name, c.name as catname,
(SELECT name FROM categories d WHERE d.ID=c.parent) as fparent
FROM Products p, Categories c
WHERE p.catID=c.ID
Если нужно выбрать только продукты, у которых обязательно есть родительская категория, то добавьте в конец запроса "Having fparent IS NOT NULL"