Задать вопрос
@ndlx

Как сделать категории в интернет магазине?

Ознакомился со способами хранения иерархических структур
https://habr.com/ru/companies/bimeister/articles/6...

Выбрал Adjacency List, итого есть таблица с колонками
ID TITLE PARENT_ID
Сам каталог может быть сколь угодно вложенным
Есть так же таблица товаров

Но уже столкнулся с проблемой выбора по всех товаров по родителю
Например двум товарам назначены категории: одному Телефоны, другому Планшеты
И я не могу понять как получить все товары по их родительской категории - Электроника

Мне подсказали что надо использовать CTE запрос, но я плохо знаком с ними, и не могу найти подходящий пример

Из-за этого в целом сомнения касательно самого хранения категорий
Может кто-то знает как это устроено в других системах? Способ хранения и способ получения всех товаров, чьи категории входят сколько угодно много по вложенности
  • Вопрос задан
  • 379 просмотров
Подписаться 1 Простой 7 комментариев
Пригласить эксперта
Ответы на вопрос 4
ThunderCat
@ThunderCat
{PHP, MySql, HTML, JS, CSS} developer
очевидным решением в лоб выглядит добавление поля root_id, что поможет быстро вытащить нужную ветку. А дальше уже логикой приложения ограничить вывод...

Где-то тут давно пробегало решение с рекурсивным запросом, но сейчас уже не вспомню как там было, но оно и так вроде гуглится. С другой стороны не уверен что запрос будет эффективнее пересчета на бэкенде...
Ответ написан
@alexalexes
Пишется один рекурсивный запрос одного из видов (или оба вида, чтобы два раза не вставать).
1) Получения списка детей, если известны параметры родителя (до определенного уровня, с пропуском неважных уровней).
2) Получения списка предков (до определенного уровня, с пропуском неважных уровней), если известны параметры ребенка.
Выносите эти запросы в секцию with, даете им понятные псевдонимы.
Далее ниже по тексту пишите уже привычные запросы, используя эти псевдонимы, словно это view или кеш-таблицы.

PS: Если иерархическая выборка нужна в подзапросе, и она зависит от изменяемых в ходе выборки входных параметров ребенка/родителя, то тут нужно выносить 1 и 2 в хранимые функции, где результат функции будет табличный курсор. При использовании результата этого курсора, обычно, делают преобразование результата функции в тип "таблица" через выражения cast.
Ответ написан
Комментировать
ipatiev
@ipatiev
Потомок старинного рода Ипатьевых-Колотитьевых
Да в том-то и дело, что нет такого "тру решения". Даже в той же статье, из которой вы выбрали самый неудачный вариант, приведено ЧЕТЫРЕ варианта работы с деревьями.
Высоколобые интеллектуалы считают, что тру вариант - это вложенные множества.
Люди попроще используют материализованный путь. Из него по разделителю вырезается корневая категория телефонов, и дальше одним запросом с LIKE выбираются все дети.

В вашем же случае самый тупой вариант - это два цикла в приложении, которое работает с БД:
Сначала циклом пройти от телефонов верх, получая родителя, пока он не вернет пустоту. это будет корневая категория
А потом в цикле пройти вниз, получая всех детей, и добавляя их в WHERE IN, пока запрос не вернет то же количество записей, что и предыдущий - то есть, мы дошли до дна. И подставить полученный список в таблицу товаров.

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

А если вам нужен прямо CTE запрос, то во-первых, ставьте нормальные теги, во-вторых, приведите нормальные дампы таблиц (а не вот это на пальцах "ну есть телефончики..."), и тегайте Akina и Slava Rozhnev
Ответ написан
mayton2019
@mayton2019
Bigdata Engineer
Для выскоконагруженных интернет магазинов нет прямого доступа к категориям в БД.
Они (категории) кешируются на стороне приложения и NGinx.

Категории меняются редко. Ну вряд-ли в течение дня. Скорее всего на следующий день.
Поэтому форма хранения их в таблице должна выбираться из удобства внесения изменений.
Вот попробуйте Adjacency List. Самый первый и самый очевидный вариант.

И не надо быть перфекционистом и ковырять грязь из под ногтей. Просто потеряте кучу времени.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы