БД дизайн для хранения различных продуктов для каждого заказа клиента - PullRequest
0 голосов
/ 14 декабря 2011

Я строю простой способ вставки заказов клиентов в БД.У нас есть несколько продуктов, каждый из которых нуждается в разных свойствах.

Я начал проектировать следующие таблицы:

CUSTOMER -> Order (FK to CUSTOMER) -> OrderItem (FK to Order)

Теперь я думаю, как связать таблицы конкретных продуктов с OrderItem .Предположим, у меня есть два продукта: product1 (имя комнаты, ширина, высота, цвет) и product2 (число, ширина, высота, тип, опции) .Я бы создал две разные таблицы и связал бы их с OrderItem , чтобы получить конкретные опции, я не прав?(конечно, будет больше, чем просто два продукта)

Как я могу это сделать?

Ответы [ 4 ]

2 голосов
/ 14 декабря 2011

Вот несколько вариантов

  1. ИМХО Я бы выбрал шаблон наследования, то есть новую таблицу с именем "ProductBase" с уникальным суррогатом.Товарная база будет иметь классификацию, например «ProductType», которая позволит вам присоединиться к соответствующей таблице «подкласс» Product.OrderItem будет ссылаться только на суррогат.Ссылочная целостность является обязательной и дает возможность распространяться на дополнительные формы продуктов.Тем не менее, он требует использования общего уникального суррогата среди всех типов таблиц Product.Если есть другие таблицы (кроме OrderItem), ссылающиеся на Product, это также позволит избежать необходимости использовать FK для составных ключей.

  2. Обнуляемые внешние ключи в OrderItem, т. Е. OrderItem будет иметь значение NULL.FK для обоих (всех) типов таблиц товаров, хотя в каждой строке будет присутствовать только один из них.Внутреннее присоединение OrderItem к соответствующим таблицам Product устранит «неправильные» объединения продуктов, основанные на NULL.RI по-прежнему можно применять.

  3. Если у вас есть ЖЕ тип первичного ключа во всех ваших таблицах подклассов Product, то вы также можете добавить один «внешний» ключ Product и «ProductType»"" Переключить "на OrderItem.Проблема здесь в том, что вы не можете применять RI.

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

Нет сомнений, что если вы продаете самолеты и продукты, которые вам, вероятно, понадобятся AircraftProduct и GroceryProduct , но A300 , Boeing 747 и Cessna Skyhawk поместятся в виде строк внутри AircraftProduct , даже если есть несколько необязательных полейв каждой таблице не применимо ко всем продуктам в этой «категории»?

Редактировать : сначала посмотрите сообщения Демса и Даффмо, чтобы узнать, можете ли вы вообще отказаться от необходимости иметь несколько таблиц продуктов,с помощью шаблонов EAV / Multivalue / Metadata для моделирования Product.

1 голос
/ 14 декабря 2011

Вы пометили вопрос как django. Тогда вам следует прочитать этот недавний пост:

Кодирование системы инвентаризации с полиморфными элементами и управляемыми типами элементов

В этом посте @ThibaultJ объясните, как этого добиться с помощью Django model utils .

Идея состоит в том, что у вас есть модель 'product', и вы наследуете product1 и product2 из этой модели, добавляя конкретную информацию для обоих. @ThibaultJ опубликовал интересные примеры.

Я замечу @ThibaultJ по этому вопросу. Если @ThibaultJ напишет ответ, я удалю свой пост.

1 голос
/ 14 декабря 2011

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

Большинство людей уклоняются от нескольких столов.Одна из причин в том, что вы не знаете, сколько таблиц вы можете получить в будущем.Другая причина состоит в том, что ваши запросы могут также раздуты, если вам нужно объединить несколько таблиц.И это может стать головной болью при обслуживании с несколькими запросами, которые обновляются каждый раз, когда вы добавляете таблицу.Наконец, добавление таблицы даже удаленно не так удобно, как добавление записи (вы действительно хотите, чтобы ваше приложение могло создавать таблицы?).

Один из вариантов - просто добавить все больше и больше полей в таблицу Product.Делая поля свойств равными NULL, разные продукты могут использовать разные поля.

Но ... Затем вам может понадобиться добавить логику, чтобы убедиться, что ProductX - всегда - имеет значение в FieldA, но что ProductY всегда имеетзначение в FieldB и т. д. И, возможно, некоторые метаданные о каждом типе продукта, чтобы ваше приложение знало, какие поля использовать для каких продуктов.Вам по-прежнему может потребоваться добавить новые поля, что, возможно, более аккуратно, чем добавление новых таблиц, но, тем не менее, вы, вероятно, не хотите, чтобы это делало Приложение.

Опция, которая полностью исключает использование DDL для добавления продукта, заключается в дальнейшей нормализации ваших данных и наличии свойств продукта в таблице Entity-Attribute-Value. изначально очень привлекателен для многих людей, поскольку он настолько универсален и гибок.

  • Продукт (идентификатор, имя, другое глобальное свойство и т. Д.)
  • Product_Properties (product_id, property_id, property_value)

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

Но какого типа должно быть «значение свойства»?Возможно, потребуется хранить строки, даты, числа, что угодно.Вы можете сделать это строкой и использовать метаданные, чтобы знать, как ЗАКАЧИТЬ значение.У вас может быть несколько полей значений, по одному для каждого типа, и «field_type_id» или что-то, что указывает, из какого поля значения следует читать.

Это также менее удобно для определенных поисков.Если вы знаете product_id, найти свойства легко.Если вы хотите, чтобы все продукты с истекшим сроком годности были в прошлом, вы должны быть осторожны с тем, как вы структурируете данные и индексы, чтобы сделать запрос эффективным.Но если вы хотите (истекает <сегодня И стоимость> 50), тогда вы получите запрос, совершенно не похожий на тот, к которому вы привыкли - каждое значение находится в другом ROW, а не в другом ПОЛЕ.

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

Какой путь вы выберете, зависит от функциональных требований приложения, архитектуры и дизайнерских решений, а также от полезного «вкуса».

1 голос
/ 14 декабря 2011

Я бы имел одну Product таблицу с отношением один-ко-многим между OrderItem и Product. Поместите FOREIGN KEY в таблицу OrderItem, которая указывает на связанный Product.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...