ФорумРазработкаБазы данных → Запрос, который выводит категории и подкатегории сразу

Запрос, который выводит категории и подкатегории сразу

  • Rotten

    Сообщения: 2243 Репутация: N Группа: Адекваты

    Spritz 7 декабря 2008 г. 20:00

    Всем доброго времени суток.
    Есть вопрос один по поводу майскюельного запроса…
    Короче говоря, так. Предметная область: нет-магазин.
    Что надо? Как не банально - но вывести(какая бы то страница не была) в левой/правой стороны сайта список всех категорий и подкатегорий товаров
    (чтото наподобе
    +Аудиосистемы (Категория)
    -Магнитолы (подкатегрия 1)
    -Аудиоплееры (подкатегрия 2)
    -Муз. центры (подкатегрия 3)
    )
    Ну это понятно….почти на каждом магазине так….
    Шо меня интерессует: Как именно сложыть такой запрос, который будет выводить каждую категорию(и вложенную в нее подкатегорию) этих товаров?

    я пробовал по-разному, но почемуто ничего толкового в голову не лезет…
    Итак…структура моих таблиц…
    их три: Категории, Субкатегории и естессно их же таблица связей.

    Структура:
    Категории(cat): cat_id(FK),cat_name
    Субкатегории(subcat): subcat_id(FK),subcatcat_name
    Таблица связей(relations): cat_id(PK),subcat_id(PK) …. соответственно.

    Шоб выбрать все со всех таблиц я конешно же генерю одну таблицу из трех
    "SELECT DISTINCT * FROM cat LEFT JOIN relations
    ON relations.cat_id=cat.cat_id
    LEFT JOIN subcat
    ON relations.subcat_id=subcat.subcat_id
    ORDER BY cat.cat_id ASC"

    И конешно же запрос (mysql_assoc) возвращает соответственное количество строк…..

    Array
    (
    [cat_id] => 1
    [cat_name] => Аудиосистемы
    [subcat_id] => 7
    [subcat_name] => Аудиоплееры
    )

    Array
    (
    [cat_id] => 1
    [cat_name] => Аудиосистемы
    [subcat_id] => 5
    [subcat_name] => Магнитолы
    )

    Array
    (
    [cat_id] => 2
    [cat_name] => Канцелярия
    [subcat_id] => 4
    [subcat_name] => Карандашы
    )

    Array
    (
    [cat_id] => 2
    [cat_name] => Канцелярия
    [subcat_id] => 8
    [subcat_name] => Шариковые ручки
    )



    Вообщем, из содержымым бд понятно….
    Идем дальше…
    Шалон.
    В шаблоне я вывожу шото типа массива(который передает сюди контроллер):
    (foreach)
    <tr><td><a href = "?cat={$cat_id}">{$cat_name}</a></td></tr>
    <tr><td><a href = "?cat={$cat_id}&subcat={$subcat_id}">{$subcat_id}</a></td></tr>
    (/foreach)

    Ну и как результат оно выводит совсем не так как требуеться…
    +Аудиосистемы
    -Аудиоплееры
    +Аудиосистемы
    -Магнитолы
    +Канцелярия
    -Карандашы
    +Канцелярия
    -Шариковые ручки

    Вообщем, и не странно, обо в нашем случае в шалоне пара из двух строк это и есть каждая строка запроса
    Итак…..теперь собсно говоря сам вопрос…
    Какое можно в бд-запросе написать условие, чтобы запрос возвращал чтото наподобие
    такого(в случае mysql_array ибо assoc тут я думаю не покатит изза неуникальных названий ключей массива)
    Array
    (
    0=> [cat_id] => 1
    [cat_name] => Аудиосистемы

    1=>([subcat_id] => 7
    [subcat_name] => Аудиоплееры)

    2=([subcat_id] => 5
    [subcat_name] => Магнитолы)
    )

    Array
    (
    0=>([cat_id] => 2
    [cat_name] => Канцелярия)
    1=>([subcat_id] => 4
    [subcat_name] => Карандашы)
    2=>([subcat_id] => 8
    [subcat_name] => Шариковые ручки)

    )




    Может быть ошыбка наверное не в запросе как именно в выводе шаблона…..неправильно построил этих 2 строки…хотя и с другой стороны как по другому то вывести все в одном цыкле - тот еще вопрос.

    Пока я тут писал эту тему я одновременно дальше пробовал разбираться над этой проблемой…и что мне в голову пришло: самые категории в шаблоне надо позадавать явно….тоесть из ссылкой типа "?catid=1" и название ссылки тоже явно…Вот лишь все подкатегории повыводить запросом в зависимости от номера категории…
    хотя….что выходит?…..ладно я еще в этом примере вывел две категории(значит 2 запроса)….а если категорий штук 50…..тогда и 50запросов сразу?……не, это тяжко скажеться на оптимизаци…
    Вообщем, господа, я здаюсь…
    Чем можете, памагите, буду очень благодарен…


  • disc

    Сообщения: 843 Репутация: N Группа: Джедаи

    Spritz 7 декабря 2008 г. 23:36, спустя 3 часа 36 минут 2 секунды

    Тебе надо использовать "Вложенные множества" (NESTED SETS). Более подробно читай тут.
    У себя я данную реализация сделал в БД с помощью функций. Данная тема не первый раз подымалась на форуме, соберусь с мыслями и временем и напишу статью как это (не)надо юзать.
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 8 декабря 2008 г. 12:30, спустя 12 часов 53 минуты 33 секунды

    disc, опередил :)

    Nested Sets будут незаменим если мы хотим получать данные из папки + данные из под-папок, вложенных в эту папку.
    Надо ли? Я сходу не могу вспомнить интерфейс где бы такое встречалось.

    Обычно интерфейс строится по подобию проводника Windows - структура папок + содержимое одной "текущей" папки - тогда все просто. По отптимизации могу кое-что подсказать из личной практики:

    1) Структура меняется не очень часто и она может большая но не огромная — разумно хранить ее в каком-то кеше в виде готового массива на php и подбирать когда надо. Кеш перестраивается только по команде админа.
    Предположим структура хранится в одной таблице (id, parent_id, name). А в кеше храним ее как массив с элементами-массивами.

    2) Если в каждый момент времени требуется выводить товары только из одной конечной подкатегории, значит
    структуры в самом запросе нет !!! Он прост как ведро: select * from items where cat_id=###

    После выполнения запроса по товару, на базе "кеша подкатегорий" строим путь от корня до текущей подкатегории.
    Процедуры обхода дерева описаны во всех учебниках по информатике. У нас готовый массив, поэтому обход будет происходить мгновенно.
    Визуально путь может выглядеть как дерево или как хлебные крошки + список подпапок данной папки — не суть важно.
    ιιlllιlllι унц-унц
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 7 января 2009 г. 17:50, спустя 30 дней 5 часов 20 минут


    disc, опередил :)

    Nested Sets будут незаменим если мы хотим получать данные из папки + данные из под-папок, вложенных в эту папку.
    Надо ли? Я сходу не могу вспомнить интерфейс где бы такое встречалось.

    Обычно интерфейс строится по подобию проводника Windows - структура папок + содержимое одной "текущей" папки - тогда все просто. По отптимизации могу кое-что подсказать из личной практики:

    1) Структура меняется не очень часто и она может большая но не огромная — разумно хранить ее в каком-то кеше в виде готового массива на php и подбирать когда надо. Кеш перестраивается только по команде админа.
    Предположим структура хранится в одной таблице (id, parent_id, name). А в кеше храним ее как массив с элементами-массивами.

    2) Если в каждый момент времени требуется выводить товары только из одной конечной подкатегории, значит
    структуры в самом запросе нет !!! Он прост как ведро: select * from items where cat_id=###

    После выполнения запроса по товару, на базе "кеша подкатегорий" строим путь от корня до текущей подкатегории.
    Процедуры обхода дерева описаны во всех учебниках по информатике. У нас готовый массив, поэтому обход будет происходить мгновенно.
    Визуально путь может выглядеть как дерево или как хлебные крошки + список подпапок данной папки — не суть важно.

    интернет магазин с ходу тебе пример :)

    там когда выбираешь категорию процесоры - надо показать все марки, а не только кто в "категории процессоры". нестед сетс - хороший механизм.
    Сапожник без сапог
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 8 января 2009 г. 7:47, спустя 13 часов 57 минут 9 секунд


    интернет магазин с ходу тебе пример :)

    там когда выбираешь категорию процесоры - надо показать все марки, а не только кто в "категории процессоры". нестед сетс - хороший механизм.

    в тех магазинах где я тарюсь (sunrise, разные фото-*) товары из вложенных категорий НЕ показываются.

    а нестед сет - круто, никто не спорит. например если надо посчитать сколько всего товара во вложенных подкатегориях, с (id,parent_id) зае*ся, а в нестед сет одним запросом делается. для всевозможной статистики это клад!

    у меня сомнения насчет того, что это даст какие-то плюсы посетителю интернет-магазина! товар ищется либо
    а) поиском по названию - здесь структура пох*, либо
    б) последовательными переходами по категориям: от общего к частному.
    так вот если без ума фанатеть по нестед сет, на страничке должны сначала вывестись ВСЕ ТОВАРЫ (ну или первая страница из ох*ного списка), а потом кучками все меньше и меньше. это полная чушь!!!
    ιιlllιlllι унц-унц
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 8 января 2009 г. 11:49, спустя 4 часа 1 минуту 20 секунд



    интернет магазин с ходу тебе пример :)

    там когда выбираешь категорию процесоры - надо показать все марки, а не только кто в "категории процессоры". нестед сетс - хороший механизм.

    в тех магазинах где я тарюсь (sunrise, разные фото-*) товары из вложенных категорий НЕ показываются.

    а нестед сет - круто, никто не спорит. например если надо посчитать сколько всего товара во вложенных подкатегориях, с (id,parent_id) зае*ся, а в нестед сет одним запросом делается. для всевозможной статистики это клад!

    у меня сомнения насчет того, что это даст какие-то плюсы посетителю интернет-магазина! товар ищется либо
    а) поиском по названию - здесь структура пох*, либо
    б) последовательными переходами по категориям: от общего к частному.
    так вот если без ума фанатеть по нестед сет, на страничке должны сначала вывестись ВСЕ ТОВАРЫ (ну или первая страница из ох*ного списка), а потом кучками все меньше и меньше. это полная чушь!!!

    у санрайза в магазине наверное тупо подкатегорий даже нету))))) а проблема такая есть ….
    Сапожник без сапог
  • Givi

    Сообщения: 2284 Репутация: N Группа: Адекваты

    Spritz 8 января 2009 г. 12:06, спустя 17 минут 25 секунд

    Да для многих вещей Nested Sets полезна. Например карту сайта построить - раз, запросик один, и готово :) И не нужно тогда кэшировать все это дело. А используется это нынче на значительной части сайтов.
  • md5

    Сообщения: 11960 Репутация: N Группа: в ухо

    Spritz 9 января 2009 г. 9:57, спустя 21 час 51 минуту 6 секунд

    а я думал, сарай только у нас есть…
    все умрут, а я изумруд
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 10 января 2009 г. 9:12, спустя 23 часа 14 минут 34 секунды

    phpdude, не хочу рекламировать санрайз :) но для ленивых могу расказать про их иерархию: категории у них строго трехуровневые и пронумерованы классически

    02. Ноутбуки, КПК, смартфоны, GPS
    2.01. Ноутбуки менее 14"
    2.1.01 Ноутбуки менее 14" ASUS

    товары есть только у конечной категории. при таком строгом подходе можно придумать запросы очень напоминающие Nested Set. типа:

    SELECT count(*)
    FROM items AS i
    INNER JOIN categories AS c ON i.cat_id=c.id
    WHERE c.cat_no LIKE '2.%.%'

    просекли фишку?
    фактически категории можно хранить в "плоской" таблице, всю иерархию реализовать разбором номера, не заморачиваясь id-parent_id или left-right.
    схема неуниверсальная, но рабочая!
    ιιlllιlllι унц-унц
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 10 января 2009 г. 9:28, спустя 16 минут 24 секунды

    artoodetoo, нахуй такие подходы. а потом начальник скажет! я не хочу товары расписывать по 3 категориям, "я хочу продавать семечки!" в категории "все товары -> семычки")))))))

    не, просто сан райз был сделан тогда, когда еще нестед сетс не применяли я думаю …. )) если мы про это http://sunrise.ru/
    Сапожник без сапог
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 10 января 2009 г. 9:29, спустя 53 секунды

    каталог там еще и на .нете …. ахуеть.
    Сапожник без сапог
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 10 января 2009 г. 18:27, спустя 8 часов 57 минут 21 секунду

    вообщто я имел в виду наш местечковый санрайз, но помоему они одинаковые )))
    вот на чем сделан сайт - вообще мало*бучий фактор. мы вродебы алгоритм и структуру данных обсуждаем.
    помоему надо подходить к задаче "от киента". что будет понятно и удобно ему, а не программисту или хозяину.

    - нужна клиенту возможность смотреть семечки с ноутбуками в одном списке?
    - нужно ему знать сколько всего видов товара в категории "злаки", включая подкатегории?
    - интересует его сколько SQL запросов было вызвано чтобы нарисовать список семечек?
    НЕТ

    - поиск по любой части названия?
    - опережающий ввод при наборе названия?
    - узнать есть товар на складе или надо заказывать?
    ДА

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

    мне тоже когдато казалось что успешные программы должны внутри выглядеть красиво, а теперь я знаю что размер шрифта и стиль речи в текстах продаются лучше!

    извините за многословность! возвращаясь к топикстартеру скажу: если не получается собрать данные в один запрос, сделай в два. похуй! а если у тебя получается 50 запросов, значит надо ставить реальные цели, а не хуйню. вернись к формулированию вопроса.

    Структура:
    Категории(cat): cat_id(FK),cat_name
    Субкатегории(subcat): subcat_id(FK),subcatcat_name
    Таблица связей(relations): cat_id(PK),subcat_id(PK) …. соответственно.

    полная хуйня! таблицы связей хороши только на уроке информатики.

    делай так:
    - категории и подкатегории - это записи из одной, а не из двух таблиц. отношения между записями можно задать
    а) с помощью ссылки parent_id. тогда подкатегории выбираются как
    SELECT cat_id, cat_name FROM categories WHERE parent_id=:ID
    б) как вложенные множества. подкатегории выбираются как
    SELECT cat_id, cat_name FROM categories WHERE left between :MYLEFT and :MYRIGHT
    в) как номер категории в виде текста:
    SELECT cat_id, cat_name FROM categories WHERE cat_no like 'XXX%'

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

    - товар хранится в своей таблице и в любом случае выбирается одинаково.
    SELECT item_id, item_name FROM items WHERE cat_id=:ID

    ВСЕГО ДВА ЗАПРОСА В ЛЮБОМ СЛУЧАЕ

    для такой простой задачи как отрисовка страницы "товары из категории X и список подкатегорий X" все способы одинаково хороши. не будем ебать себе мозг. nested set в данном случае ничего не дает.

    человек не умеет писать элементарные запросы, а мы ему говорим: "а вот есть еще замечательная штучка, почитай про нее". а зачем?????
    ιιlllιlllι унц-унц
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 10 января 2009 г. 23:26, спустя 4 часа 59 минут 16 секунд

    а зачем?????
    а чтобы когда нибудь начать учиться :)
    Сапожник без сапог
  • adw0rd

    Сообщения: 22959 Репутация: N Группа: в ухо

    Spritz 11 января 2009 г. 10:23, спустя 10 часов 56 минут 57 секунд


    а я думал, сарай только у нас есть…


    он по всей россии есть
    https://smappi.org/ - платформа по созданию API на все случаи жизни
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 11 января 2009 г. 11:04, спустя 40 минут 49 секунд

    сарай - россия.
    Сапожник без сапог

Пожалуйста, авторизуйтесь, чтобы написать комментарий!