Проектирование таблицы при отношениях 'многие-ко-многим'

Есть две таблицы:

  • Товары Goods с полями:

    • id
    • name
    • number
    • price
  • Заказы Orders с полями:

    • id
    • data [{goods_id: string(GUID), name: string, number: string, price: integer}]
    • sum
    • datetime

Отношения между ними похожи на многие-ко-многим, т.е. надо сделать промежуточную таблицу OrdersGoods, пусть это будет простейший вариант только с тремя полями id, goods_id и orders_id.

В таблице Orders одна запись (строка) - это один заказ, т.е. все данные надо уместить в одну строку. Но поле data (массив словарей) выглядит ужасно. Видимо, сам замысел неверен.

Как сделать правильно?

Ответ можно дать на диалекте любой реляционной СУБД.


Ответы (2 шт):

Автор решения: Faraday

OrderGoods (Order один, так как иерархически главнее) не должен иметь Id, поскольку его Id (т.е. primary key) это комбинация product_id и order_id. Так же сюда додайте goods_count, что бы указать, сколько однотипных продуктов у вас было добавлено в order (если у вас НЕ действует логика один товар - один рекорд)

Orders будет иметь только id, и какие-то мета-данные, типа created_on, deleted_on, is_payed, owner_id и т.д. Его связь с самими товарами будет обеспечена связующей таблицей OrderGoods

UPD: На сколько я вижу, вы пишете в основном на C#. Думаю эта статья будет вам крайне полезна при конфигурации через Entity Framework

→ Ссылка
Автор решения: InterceptorTSK

Таблиц должно быть гораздо больше.

Простая сущность Good на самом деле - это ProductForSale. Продаваемых и не продаваемых сущностей может быть множество типов. Что бы заранее не перепутать типы - нейминг важен. Продукт/товар для передачи существует, на уничтожение существует, и так далее. Но у всех этих продуктов/товаров - разное назначение, разные поля итд.

Продукт/товар всегда в некоторой партии. Это важно, у продукта есть партия продуктов.

Продукт/товар не должен содержать цены, см. ниже.

В простейшем приближении получается следующее.

Продукт/товар на продажу ProductForSale

    LongDateTime (время появления ProductForSale, Id)
    PartNumber
    Product
    Data [PartNumberDocument0, PartNumberDocument1]
    ...

Почему партия? Потому что обычно на партию товара - одинаковые условия. Меняем партию - меняем условия. Партия обозначает [ссылается] на документ, это важно. Иначе говоря поступили 20 видеокарт - у них свой документ [ворох документов], ровно на эти 20 видеокарт.

Продукт на продажу ProductForSale ссылается собственно на продукт.

Продукт/товар Product

    LongDateTime (время появления Product, Id)
    Name
    ...

Продукт видеокарта "такая то" меняется от партии к партии, такое возможно. Иначе говоря Product существует строго в пределах партии. Но этот же продукт слегка изменившись полями может легко стать немножко другим продуктом. Вот эти тонкие изменения должны быть учтены.

Далее нужна таблица например продажных цен, строго на партии товара. Эти таблицы не обновляются, но добавляются с новыми ценами. Тут могут быть цены закупки/продажи итд. Из этих таблиц берутся цены как таковые. Этих таблиц очень много.

PriceList

    LongDateTime (время появления PriceList, Id)
    Data [ProductForSale0, SalePrice110, ProductForSale1, SalePrice234]
    ...

Ровноодинаково, существует таблица уничтожения товара, это товар на списание, на уничтожение. Но этот товар - снова завязан на партии товара, и на документы сопровождающие. Пусть существует DestroyList. И таких DestroyList очень много. Ровноодинаково существуют RepairList, ExchangeList и так далее. "Где то и как то" должны быть отображены товары в партиях, и с документами.

DestroyList

    LongDateTime (время появления DestroyList, Id)
    Data [ProductForDestroy0, ProductForDestroy11]
    ...

Заказ - это отдельная сущность. Заказ может быть, а может не быть. Заказ не обязателен к продаже. Заказ - это скомпонованная куча товаров/продуктов, на кого-то оформленная [или не оформленная], к кому то прикреплённая, к человеку/компании. Они [человек/компания] называются - Заказчики (Customers).

Т.е. нужно описать таблицу Customer, это таблица заказчиков, с [может быть] их номерами телефонов, Именами, Названиями компаний. Понятное дело и тут нужны [возможно] разные типы.

Заказ SaleOrder

    LongDateTime (время появления SaleOrder, Id)
    State
    Customer
    TimePrice (на момент LongDateTime)
    Data [ProductForSale0, Quantity10, ProductForSale1, Quantity5]
    ...

И существует продажа как таковая, Sale. Но продаж опять же множество типов, они разные. Sale содержит Заказ и цену, строго на момент Sale. И множество чего то, на момент Sale.

Продажа Sale

    LongDateTime (время появления Sale, Id)
    State
    TimePrice (на момент LongDateTime)
    Data [SaleOrder0, SaleOrder1]
    ...

Это очень простой кейс. Но учитывающий самое необходимое. Без жёсткой привязки к оптимизациям. Суть не в этом. Суть в сущностях, оптимизаций здесь нет. Допишите всё, что ещё необходимо и хотя бы достаточно.

→ Ссылка