Вариант с горизонтальным растяжением таблицы при добавлении новой характеристики (у тебя это "опции") товара даже не рассматривается?
Dagdamor Неа, не рассматривается. У меня-то товаров не много в базе, порядка 100-300 будет, поэтому можно и рассмотреть. Но мне такое решение не нравится в корне: 1. Не красиво 2. Не удобно (ковырять лишние параметры) 3. Если представить, что у меня в базе 50 типов товаров и каждый обладает десятком уникальных свойств. Не очень хочется видеть таблицу с продукцией, где 500 атрибутов, которые используются через сотню-другую :lol:
Kreker Что есть красиво, а что некрасиво? Хранить данные разного типа в одном поле - красиво? Какие именно? Это магазин или выставка сферических коней в вакууме? На практике количество атрибутов не превышает 20-30, причем независимо от общего количества товаров в магазине. По одной простой причине - вести такой магазин иначе становится невозможно.
Dagdamor У меня в админке при выборе типа товара будут подгружаться его возможные свойства, чтобы при добавлении телевизора не было возможности выбрать тип HEPA-фильтра А возможно ли определить, какие свойства допустимы у категории товара, если заведомо неизвестно, все ли поля заполнены у первого попавшегося товара категории? А разве красиво когда у товара десяток лишних нуль-полей? Незнание точного количества полей в таблице - не есть хорошо, все конструкция получается плавающей. Сайт работает на заранее неизвестных данных. При добавлении нового свойства, приходится добавлять новое поле, а значит, перелопачивать всю таблицу. При добавлении нового свойства необходимо и задуматься о его имени. Адмонимус - вещь неожиданная. Лично мое мнение, что горизонтальное расширение таблицы принесет слишком много гемора. Не хочу, не буду. Занимался этим спустя полгода сайтописания, но быстро перестал.
Kreker Если при создании нового товара есть возможность определить, какой у него список характеристик, как получается, что при редактировании товара ты этого узнать уже не можешь? А разве красиво, когда для выбора половины свойств товара нужен один запрос, а для выбора второй половины - другой? Незнание точного количества товаров в каталоге - не есть хорошо, все конструкция получается плавающей. Сайт работает на заранее неизвестных данных. Разумеется. Однако чего вы все так трясетесь при мысли об одном ALTER TABLE в административной зоне - не понимаю. Ну допустим, миллион товаров в таблице. Ну допустим, запрос будет работать минуту, приостановив работу магазина на эту самую минуту. Это критично? Ты гораздо больше потеряешь на лишних запросах к таблицам-связкам, а ведь эти лишние запросы будут выполняться не раз в неделю, а сотни раз в секунду. А если товаров немного - тысячи или десятки тысяч - таблица перестраивается за доли секунды, максимум за несколько секунд на самом старом и унылом железе. Не бойтесь вы структуру таблицы менять, как дети, право слово. Да, это серьезная проблема Как раз возня с дополнительными таблицами принесет намного больше гемора. Сравни типичные запросы - например, показать страницу каталога. В случае одной таблицы и запрос будет один: [sql]SELECT * FROM shop WHERE categoryid=$id ORDER BY title LIMIT 0,20[/sql] Все просто и удобно - выбрали 20 товаров, каждая строка результата хранит все данные товара, никаких дополнительных телодвижений. А в случае связок сколько будет запросов и каких, и как все это выводить? Вот же он, геморрой, во всей своей красе. Хех. Какие же тут все... одностороннеориентированные
Если нужна производительность, то однозначно горизонтальное расширение. В объектом подходе столкнёшься с тем, что сортировку по доп. полям нормально не сделать, а выборка будет представлять из себя кучу джоинов таблицы самой на себя. Если же доп. поля нужны только для описания характеристик, то я бы предпочёл объектную модель.
Koc Я поставил Mysql workbench, но пока ставился третий фреймворк, я не вытерпел и нарисовал в фотошопе)
Kreker Все же прошу привести примеры запросов для твоего варианта (задача та же - выборка N товаров из одной категории магазина для отображения страницы каталога), просто чтобы сравнить... все познается в сравнении...
Запроса два: первый выбирает товары, второй свойства. Я думаю, понять, как выбираются товары таким методом для тебя не составит труда. Касаемо такой реализации - я от нее отказался в пользу product_options id product_type product_id name value
Kreker Пожалуйста, конкретный запрос (запросы), чтобы я мог оценить работоспособность и скорость. На пальцах всем все и так понятно; но на пальцах магазин работать не будет. Я привел конкретный пример, сделай то же самое плиз. В частности, интересует, что будет в WHERE во втором запросе. UPD: А еще очень настораживает фраза "куча джоинов таблицы самой на себя"... в общем жду пример
Что-то типа этого [sql] SELECT `products`.`name`, `product_types`.`name` as `category` FROM `products`, `product_types` WHERE `products`.`product_type`=`product_types`.`id` ORDER BY `category` /* Выборка продуктов */ SELECT `options`.`value`, `type_options`.`name` FROM `type_options`, `options` WHERE `type_options`.`product_type` IN ('.implode(",", $products_type).') AND `options`.`product_id` IN ('.implode(",", $products_id).') AND `options`.`opt_id`=`type_options`.`id` ORDER BY `type_options`.`product_type` /* Выбираем свойства */ [/sql]
Kreker Спасибо. Замечания: 1. Первый запрос случаем не всю таблицу выбирает? Конкретных условий типа "catid=123" вообще не видно... 2. Второй запрос представляется очень тормозным. 3. Имхо, достаточно одного имплода - по $products_id. (Молодец, что без подзапросов ) 4. У тебя получается, что второй запрос возвращает в куче свойства сразу для всех выбранных товаров, причем свойства эти отсортированы не в том же порядке, что и товары, т.е. они перемешаны. Как планируешь отображать свойства товаров на странице? (можно на пальцах)
так-с, вопросище такой. Что лучше, более производительней: PHP: <?php $str = 'некое множество чисел через запятую'; $sql = "SELECT tt_at_text.id, tt_at_text.value_default, tt_at_textarea.id, tt_at_textarea.value_default, tt_at_boolean.id, tt_at_boolean.value_default FROM tt_at_text, tt_at_textarea, tt_at_boolean WHERE tt_at_text.id IN (%s) OR tt_at_textarea.id IN (%s) OR tt_at_boolean.id IN (%s)"; $sql = sprintf($sql, $str, $str, $str); $result = $db->query($sql); while($row = $db->fetchrow($result)) { $defval[$row['id']] = $row['value_default']; } /* $sql = "SELECT id, value_default FROM tt_at_text WHERE id IN (%s)"; $sql = sprintf($sql, $str); $result = $db->query($sql); while($row = $db->fetchrow($result)) { $defval[$row['id']] = $row['value_default']; } $sql = "SELECT id, value_default FROM tt_at_textarea WHERE id IN (%s)"; $sql = sprintf($sql, $str); $result = $db->query($sql); while($row = $db->fetchrow($result)) { $defval[$row['id']] = $row['value_default']; } $sql = "SELECT id, value_default FROM tt_at_boolean WHERE id IN (%s)"; $sql = sprintf($sql, $str); $result = $db->query($sql); while($row = $db->fetchrow($result)) { $defval[$row['id']] = $row['value_default']; } */ ?> закомментированный вариант или раскомментированный? как еще можно улучшить такой запрос?
Koc Создай тестовую таблицу, забей ее тестовыми данными, и замерь сам, в чем проблема. На первый взгляд не определить, а заниматься мартышкиным трудом за тебя неохота Я бы сказал, оба варианта плохи. Что выборка однотипных данных из трех разных таблиц плохо, что объединение их в один мега-гемор-запрос, чтобы сэкономить количество mysql_query(), тоже плохо. Здесь беда в кривом проектировании таблиц. UPD: Первый запрос, кстати, будет работать неверно. Нет условий, связывающих записи из разных таблиц друг с другом, поэтому строки будут множиться друг на друга. Если в первой таблице 10 записей, подходящих под условие $str, во второй 20, в третьей 30, то ты получишь не 60 записей в результате, а 10*20*30=6000. Изучайте теорию SQL
Dagdamor все-таки я неправ. запрос [sql] SELECT tt_at_text_v.aid, tt_at_text_v.value, tt_at_textarea_v.aid, tt_at_textarea_v.value, tt_at_boolean_v.aid, tt_at_boolean_v.value FROM tt_at_text_v, tt_at_textarea_v, tt_at_boolean_v WHERE tt_at_text_v.gid=1 OR tt_at_textarea_v.gid=1 OR tt_at_boolean_v.gid=1[/sql] выводит кучу данных как связывать записи из разных таблиц друг с другом?
В твоем случае их не надо связывать надо просто : [sql]SELECT tt_at_text_v.aid aid, tt_at_text_v.value FROM tt_at_text_v WHERE tt_at_text_v.gid=1 UNION SELECT tt_at_textarea_v.aid aid, tt_at_textarea_v.value FROM tt_at_textarea_v WHERE tt_at_textarea_v.gid=1 UNION SELECT tt_at_boolean_v.aid aid, tt_at_boolean_v.value FROM tt_at_boolean_v WHERE tt_at_boolean_v.gid=1[/sql] Это будет самый быстрый вариант.
я с другой стороны подошёл =)) Таблица товаров =) id | pid | uid | title | options | s_desc | l_desc id - ID товара =) pid - ID родителя uid - артикул title - наименование s_desc - короткое описание (можно убрать) l_desc - полное описание (можно убрать) options - а в options храним вещи вида: [characteristics]Спецификация:[/characteristics] или [characteristics]Свойства:[/characteristics] или [characteristics]Характеристики:[/characteristics] дальше [property:[Вес]]10кг[/property] [property:[Длина]]100см[/property] [property:[Запах]]плохой[/property] свойство причем к каждой единице можно задать уникальные свойства + на основе этой системы можно понаписывать Мастеры которые будут создавать весовые товары, штучные и т.д.