Как лучше организовать учет и хранение товаров при продаже услуг с различными характеристиками?

Важно уточнить, что речь идет о хранении <i>покупок</i>, а не товаров. 

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

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

JSON-формат не подходит, так как мне нужны возможность выполнения джойнов с характеристиками товаров (например, id ресторана). Хотя, если будет серьезное обоснование, я рассмотрю возможность использования JSON. По той же причине я не рассматривал NoSQL решения, такие как MongoDB, поскольку мне нужно интегрировать это в существующую базу данных с пользователями, ресторанами и прочими элементами.
  • 17 октября 2024 г. 9:12
Ответы на вопрос 2
В вашей ситуации, когда услуги имеют различные характеристики и сутью задачи является учет их покупок, действительно существуют два основных подхода, но оба они имеют свои недостатки. Давайте рассмотрим возможные решения более подробно.

### 1. Схема с широкой таблицей
Создание одной широкой таблицы с множеством столбцов, представляющих характеристики всех услуг, может оказаться непрактичным и трудоемким в поддержке. Если характеристики услуг меняются или добавляются новые, таблица будет постоянно увеличиваться, что затруднит ее использование и управление.

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

### 3. Нормализация с использованием нескольких таблиц
Рекомендуемый вариант — нормализовать данные, разнести их по нескольким таблицам с использованием связующих таблиц. Например, можно создать:

- **Таблицу услуг**: для хранения базовой информации о каждой услуге (id, название, тип и т.д.).
- **Таблицу характеристик**: для хранения различных характеристик услуг (id характеристики, название, тип).
- **Связывающую таблицу: Услуги_Характеристики**: для связи услуг с их характеристиками (id услуги, id характеристики, значение).

Это позволит хранить любые характеристики, предотвратит дублирование и сделает добавление новых услуг или характеристик более простым.

### Пример структуры
1. **Услуги**
   - id
   - название
   - тип
   - описание

2. **Характеристики**
   - id
   - название
   - тип (например, строка, число, дата и т.д.)

3. **Услуги_Характеристики**
   - id услуги
   - id характеристики
   - значение

### 4. Использование JSON в реляционных базах данных
Если вы все-таки хотите использовать JSON для хранения характеристик, вы можете рассмотреть возможность хранения их в одной из колонок, например, в формате JSON, но при этом необходимо будет учитывать, что это может усложнить ваши SQL-запросы. Однако современные реляционные базы данных, такие как PostgreSQL, поддерживают работу с JSON и даже позволяют выполнять некоторые операции, такие как поиск и фильтрация по значениям в JSON.

### Заключение
В вашем случае, вероятно, наилучшим решением будет комбинация нормализованной структуры таблиц с возможностью хранения специфических характеристик в отдельной таблице, что поможет сохранить гибкость и расширяемость системы без излишнего дублирования и сложности при выполнении запросов.
У меня был проект с такой задачей (и тоже ресторанный). Особенностей у него три: 
Исходя из этого, выбрали именно JSON, в который складывались все связанные модели ("магазин", "товар" и т.п.) в сериализованном виде. В таком виде они хранятся год-два на всякий случай, потом старые записи переносятся в архивную таблицу, где только реально используемые на странице истории поля со скалярными типами (путь к картинке, название "магазина" и т.п.).

Но тут надо бы реальную задачу понимать. Может, не надо джойнить, а проще денормализовать данные и вести отдельные таблицы какой-то статистики? Или просто отдельно хранить те поля, по которым предполагается джойнить, а всё остальное пихать в JSON?
В отрыве от конкретных задач вариант широкой "дырявой" таблицы мне кажется самым плохим, вариант с таблицей покупки , к которой полиморфично ( properties_type , properties_id ) привязаны таблицы со значениями свойств каждого типа сущности выглядит немного лучше.
Похожие вопросы