Как лучше хранить информацию о товарах в mysql?

grey109

Новичок
Как лучше хранить информацию о товарах в mysql?

Нужно написать интернет-магазин.
Подскажите, как лучше хранить информацию о товарах в БД, при условии что для разных товаров будет храниться разная информация. Т.е., например, для сотового телефона - Общие характеристики(Диапазоны частот, Тип корпуса...), Экран(Тип экрана, Дисплей, Число строк...), Цена, для Принтера - Общие характеристики(Тип принтера, Интерфейсы, Формат бумаги, Системные требования), Печать(Тип печати, Цветная печать, Монохромная печать, Печать с двух сторон, Поддержка языка PostScript...), Цена. Неужели придется создавать для каждого типа товара отдельную таблицу с параметрами этого товара? Тогда как в это случае делать сравнее или поиск товаров?


Интересно, как это сделано на сайта типа http://market.yandex.ru ?
 

grey109

Новичок
Bred Vilchec
Спасибо за ссылку. Прочитал.

Может кто еще поделится своими мыслями?
 

Romantik

TeaM PHPClub
Сравнение между чем?
Между мобильником и принтером?
извращений много можно сделать, а смысл?
как вариант сохранять парамеры и складывать в отдельную (одну) ячейку, а при выборке по сводной таблице раскладывать параметры
 

grey109

Новичок
Romantik
Сравнение между чем?
Между мобильником и принтером?
Нет конечно. Между товарами одного типа. Но у одного товара один характеристи(вес, цена, цвет) у другого другие(цена, вес, полифония, фотокамера) - и как их сравнивать?
 

Orlis

Guest
С точки зрения нормализации данных, нужно создать таблицы 'вес','цена','цвет','полифония','фотокамера' и хранить в них данные тех товаров, для которых это имеет смысл.
 

alexhemp

Новичок
Автор оригинала: Orlis
С точки зрения нормализации данных, нужно создать таблицы 'вес','цена','цвет','полифония','фотокамера' и хранить в них данные тех товаров, для которых это имеет смысл.
C точки зрения чего?
И что для каждого нового свойства таблицу?

Все просто

1. Таблица свойств.
ID, Название

Пример:
1 Полифония
2 Поддержка PostScript
3 Количество цветов дисплея

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

ID, СВОЙСТВО_ID, Значение
Пример:
1, 1, Есть (есть полифония)
2, 1, Нет
3, 3, 16 цветов
4, 3, 65535 цветов


3. Таблица значений свойств товаров
ID, ТОВАР_ID, СВОЙСТВО_ID, ЗНАЧЕНИЕ_ID

Пример
1, 555, 3, 4 (товар 555 имеет свойство цветность 65535 цветов)

и т.п.

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

В таблице товаров хранить только название, артикулы, описания и т.п.

Вот это нормализованная структура. Сравнение пишется легко для любого типа товаров, вне зависимости от их атрибутов.

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

Для больших каталогов это не приемлимо.

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

-~{}~ 15.01.05 15:20:

да, предвидя дальнейшие возражения

1. В моей структуре используется всего 3-4 таблицы, вне зависимости от числа товаров и числа возможных параметров, списков их значений. Даже если таблица будет из миллионов строк, то выборка по индексам будет очень быстрой.

2. Поиск по параметрам пишется ОДНИМ запросом (по нескольким параметрам и нескольким значениям одновременно) причем работает на MySQL 3.23 без проблем и тоже очень быстро.

Как такой запрос написать - расскажу, если все будет ясно с предложенным методом ;-)

Иерархическая же структура параметров очень просто реализуется с привлечением dbtree - который рассматривается на этом форуме. Запросы усложняются, но вполне реальны и быстры.
 

Cougar

Кошак
Думал послать в поиск, но, как увидел такой развёрнутый (и, что главное - правильный) ответ...
Браво.
 

alexhemp

Новичок
Cougar

Щас придет Фанат и расскажет, почему я не прав :)
Сорри за оффтопик.
 

Yurik

/dev/null
alexhemp
ещё, очень важно создать таблицу которая будет нести излишние данные, но без неё очень проблематично написать интерфейс - это набор возможных свойств групы товаров. Т.е. надо ещё таблица

Группы
====
ID Имя
1 Принтеры
2 Мобильные телефоны
3 Акваланги

Возможные свойства
==========
ID Group ID_Property
1 1 1 [принтер - разрешение]
2 1 2 [принтер - скорость печати]
3 2 3 [мобилка - полифония]

Без них будет трудно нарисовать админ панель назначений свойств товара (не выбирать же в списке из 1000 свойств 5 характерных для принтеров) и рисовать таблицу описания товара (если нету полного списка возможных свойств), т.к. придётся строить интерфейс в зависимости от свойств которые встречаются хотя бы у одного выбранного товара и будет непонятно как выводить первый товар пока не проанализировать список свойств вплоть до последнего

-~{}~ 17.01.05 02:54:

Кстати ещё насчёт цен, часто может иметь смысл хранить цену не как атрибут в таблице "Товар", а как значение отдельной таблицы цен:

Код:
ID_Tovar | Date_From (Date) | Price
1   | 2004-01-05 | $10
1   | 2004-01-08 | $10
Это даёт:
- возможность указания динамики цен (как часто делают на биржах - стрелочка справа показывает направление и значение изменения цены за определенный период)
- изменение цены как свойства повлечёт неявное изменение зарегистрированных покупок, если в них цена на момент покупки не скопирована вместе с остальным содержимым корзины (id товара и к-во)
- возможность администратору магазина устанавливать цены наперёд, которые они автоматом начнут действовать с указанной даты

-~{}~ 17.01.05 02:59:

Создать UNIQUE ключ ID_Tovar+Date_From и менять цены через запрос REPLACE INTO prices (id_tovar, date_from, price) (10, '2005-01-10', '10.56')

Текущую цену выбирать
SELECT price FROM prices WHERE id_tovar=N AND date_from<=NOW() ORDER BY date_from DESC LIMIT 1
 

alexhemp

Новичок
Yurik

Это все очевидно. Я описывал самую суть.

Таблица наборов параметров - суть набор ШАБЛОНОВ. Это один (правда наиболее часто встречающийся) вариант.

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

Ввод в админке - делается по этому шаблону, а хранить его, повторюсь - можно по разному - либо таблицей для каждого узла рубрикатора товаров, либо строить при обходе дерева рубрикатора (я добавляю к описанию "свойства" одно поле - место в дереве рубрикатора).

Для вывода такой шаблон нужен есть показывать что каких-то свойств "нет", если же выводить только свойства со значениями - то это не проблема ибо в таблице значений нет "пустых" строк.


По поводу цен - это тоже как кому удобнее... Я делаю отдельную таблицу, ибо мне так удобнее переключать режимы "показывать все товары" и "показывать только товары с ценами" (в запросах меняется LEFT JOIN и INNER JOIN).

Так что вопросы эти не принципиальные и я их опустил - чтобы не усложнять пост.
 

TimBurton

Новичок
А если выгребать как Вы сказали
Текущую цену выбирать
SELECT price FROM prices WHERE id_tovar=N AND date_from<=NOW() ORDER BY date_from DESC LIMIT 1
В таком случае, если цен за сегодня нет, то соответственно старую цену не выведет поэтому не вариант.
Необходимо делать так: select Price from prices where ID_Tovar = 'ИД ТОВАРА' order by `date` desc limit 1

Кстати ещё насчёт цен, часто может иметь смысл хранить цену не как атрибут в таблице "Товар", а как значение отдельной таблицы цен:

Код:
ID_Tovar | Date_From (Date) | Price
1   | 2004-01-05 | $10
1   | 2004-01-08 | $10
Это даёт:
- возможность указания динамики цен (как часто делают на биржах - стрелочка справа показывает направление и значение изменения цены за определенный период)
- изменение цены как свойства повлечёт неявное изменение зарегистрированных покупок, если в них цена на момент покупки не скопирована вместе с остальным содержимым корзины (id товара и к-во)
- возможность администратору магазина устанавливать цены наперёд, которые они автоматом начнут действовать с указанной даты

-~{}~ 17.01.05 02:59:

Создать UNIQUE ключ ID_Tovar+Date_From и менять цены через запрос REPLACE INTO prices (id_tovar, date_from, price) (10, '2005-01-10', '10.56')

Текущую цену выбирать
SELECT price FROM prices WHERE id_tovar=N AND date_from<=NOW() ORDER BY date_from DESC LIMIT 1
Это все супер когда ты выбираешь цену для одного товара.
А когда ты выбираешь массив товаров, каким образом присоединить последнюю цену для товара?
Код:
select p.Price,p.Date_From,t.* from tovars t left join prices p on p.ID_Tovar = t.id
Данный запрос продублирует выдачу с датами:
Код:
ID_Tovar | Date_From (Date) | Price
1   | 2004-01-05 | $10
1   | 2004-01-08 | $10
очень не хотелось бы использовать вложенные запросы:
Код:
select (select scp.Price from prices scp where scp.ID_Tovar = ct.id order by scp.`Date_From` desc limit 1) as Price,ct.* from tovar ct
 
Сверху