Уважаемые форумчане. Прошу помочь советом как при помощи PHP + mySQL организовать хранение товара, статьи одновременно в нескольких категориях, разделах. Тоесть интерисует как организовать хранение в БД и корректно делать выборку при помощи PHP. Покажите хоть на пальцах.... Дальше сам расшарю.... :wink:
tarpedo Очевидный выход - вводить вспомогательную таблицу, для связи "товар-категория". Но я обычно стараюсь этого избегать, чтобы не усложнять запросы, особенно когда "мультикатегорийных" товаров немного, а также когда у товара есть понятие основной категории. В этих случаях удобнее хранить прямо несколько копий товара в таблице (последователей решений по учебникам прошу не пинать), при изменении одной копии обновляя все.
id_category в табл. с публикциями сделать строкой и хранить id категорий через запятую, выборку делать с помощью оператора IN зы. не пробовал так делать
Mr.M.I.T., думаешь будет производительнее чем с отдельной таблицей связкой? P.S. А разве IN так работает? Вроде как в этом случае только LIKE да и то гемор будет...
я такое просто видел в Data Life Engine, в нем можно одну новоть добавить в неограниченое количество категой. Может кто знает как там, а то если че поставлю гляну...
Mr.M.I.T. IN работает так: Код (Text): SELECT * FROM table WHERE id = 1 OR id = 2 OR id = 8 === SELECT * FROM table WHERE id IN (1, 2, 8)
я думаю что IN тут никак не прокати так как я буду хранить данные не о том какие товары лежат в категории, а в каких категориях лежит товар. тоесть у каждого товара будет список категорий в которых он должен находится, а не у категории список товаров, хотя это все относительно и лишь влияет на способ выборки.
Mr.M.I.T., был уверен что не работает, на всякий случай даже проверил сейчас - не воркает. karakh, LIKE был приведен чисто в качестве примера. Все эти регэкспы полнотекстовые поиски и LIKE юзать для данной цели ИМХО совершенно непроизводительно. tarpedo, я бы предпочел отдельную табличку для связки - товар/категория.
tarpedo тебе предлагают как вариант - хранить список id категорий в строковом поле базы через запятую.. можно ещё массив категорий серилизовать.. но ИМХО это всё ужасно и как выборку делать - хз.. нужно:
Именно там организовано так, как было организовано у меня до того, как я начал знакомится с MySQL - через жопу. Есть список категорий (таблица categories), есть список постов (таблица news). При записи поста в news в поле category пишутся id категорий через запятую. Например: 1,3,12. Внимание, ща будет пипец. А ищется через оператор regexp: [sql]select * from news where category regexp '[[:<:]](1|8|66)[[:>:]]'[/sql] Ищет посты с категорией 1, 8 или 66. regexp очень долгий. Замена на более быстрый like ни к чему хорошему не привведёт. Во-первых, like тоже долгий. Во-вторых, он более тупой и помимо верных результатов отдаст ещё и всякую белеберду. Тебе нужно делать так. Помимо таблицы news и catergories завести news_categories, т.е. таблицу связи с двумя полями - news_id (тут будут id постов) и category_id (id категорий привязаных к постам). Это связь называется много-ко-многим (many-to-many). Есть ещё один-к-одному и много-к-одному. Последний это обратный вариант первого. Одна группа, но много пользователей. Много пользователей, но одна группа. Выборку дкелать так: [sql]select * from news left join news_categories on (news_id = news.id) left join categories on (categories.id = category_id) where а тут основной фильтр, например news.title = 'Пенисы. Президенты. Нефть. Что общего?'[/sql] P.S. То, что предлагает Dagdamor по умолчанию тупость. Почему тупость - это изложено в первой часте поста. Оно тебе не надо, ибо ты пользоваться не умеешь, а коли так любой твой косяк приведёт к жутким тормозам и неоправданым нагрузкам на базу данных. Dagdamor использует только, если связей мало и он умеет это использовать. Ты же пользуй много-ко-многим, стандартное, из учебника и немного скушное.
lexa Эй, эй, полегче там. У тебя обострение, что ли? Если кто-то не умеет "этим" пользоваться - это еще не тупость, точнее тупость, но отнюдь не автора. Я подчеркнул, что этот способ хорош для случаев, когда среди 10000 товаров, каждый из которых в одной категории, есть с десяток товаров-исключений, лежащих в двух-трех категориях. Были у меня такие проекты, когда заводить лишнюю таблицу и автоматически гробить производительность (ведь оптимизация для сортировки и пейджинга накрывается медным тазом) - смысла не было. Э-э-э... а при чем тут первая часть поста? Там у тебя про LIKE и регэкспы. Я вообще о другом говорил, читай внимательнее.
а если допустим уже нет товаров, только категории с описанием - типичный пример многоуровневого пошагового FAQ. Тога задача значительно упращается так как надо только таблица с самим содержимым и индексная. В последней будут хнанится id родителей - тех страниц которым принадлежит текущая страница Как в таком случае поступить с упорядочиванием...
dAllonE, не, это просто потому что люблю выпендриваться. Dagdamor, я написал и про то и про другое, прочти внимательно. В том посте я про тебя ничего дурного не сказал (скажу в этом). Что ты писал не про like и regexp это я действительно попутал. У тебя ещё более тупая схема, чем было у меня с regexp. Ты её называешь много-ко-много-через-жопу? Можно изголяться с количеством полей category_id для связей, но дублировать товары, которые различные лишь категорией это полная маразмашка. tarpedo, я не очень понял суть второго вопроса. Обычно, такая штука назвается дерево. У тебя у категории есть id и есть pid (id категории родителя). Это стандартный метод, но есть и иные. И ты строишь по ним дерево. Например: id / имя / pid 1 / Первая / 0 2 / Вторая / 0 3 / Третья / 1 4 / Четвёртая / 1 Получается: - Первая -- Третья -- Четвёртая - Вторая
Самый простой и примитивный, ограничивающий действия, способ построить дерево: 1 Категория 1 1-1 Категория 1, папка 1 1-2 Категория 1, папка 2 2-1 Категория 2, папка 1 2-1-1 Категория 1, папка 1, подпапка 1 [sql] mysql> SELECT * FROM tst; +----+-------+ | id | sort | +----+-------+ | 1 | 2 | | 2 | 1 | | 3 | 1-1 | | 4 | 2-1 | | 5 | 2-2 | | 6 | 1-1-1 | | 7 | 1-2 | | 8 | 1-2-1 | | 9 | 1-2-2 | | 10 | 3 | +----+-------+ [/sql] [sql] mysql> SELECT * FROM tst ORDER BY `sort`; +----+-------+ | id | sort | +----+-------+ | 2 | 1 | | 3 | 1-1 | | 6 | 1-1-1 | | 7 | 1-2 | | 8 | 1-2-1 | | 9 | 1-2-2 | | 1 | 2 | | 4 | 2-1 | | 5 | 2-2 | | 10 | 3 | +----+-------+ 10 rows in set (0.00 sec) [/sql] Но такой способ скорее для комментариев годится...
lexa Для особо резвых на суждения и определения поясняю еще раз: если вы чего-то не понимаете, либо чем-то никогда не пользовались, либо не понимаете, как это работает - это не повод называть это "полной маразмашкой". Я так понял, ты таким методом никогда не пользовался. А я пользовался. У него единственный практический минус - это обновление (редактирование) товара, операция чуть сложнее, чем в других методах, грубо говоря "сложнее" на один запрос, но часто ли эта операция должна выполняться! Операции выборки - простые и быстрые, никаких лишних таблиц, никаких джойнов, все, включая сортировку и разделение на страницы, опирается на индексы. Никаких потерянных товаров. Никаких проблем с переносом товаров из категории в категорию. Расход памяти? Не смеши меня, ты думаешь, с дополнительной таблицей ты сэкономишь больше? Так что вполне нормальный подход, для многих ситуаций он годится прекрасно. Ну а уж как его называть - это дело воспитанности каждого.