- Интернет магазин (витрина) - иерархическая структура категорий товаров, товары, производители, поставщики, цены, характеристики товаров (у разных категорий товаров - разные характеристики).
2*). расширяем магазин - клиенты, покупки (транзакции);
3*). интеграция магазина с платежными системами - платежные системы, транзакции с платежной системой, аккаунты, счета, транзакции магазина;
Описанные сущности не являются полным и конечным ТЗ (как это и бывает в жизни). Вы как архитектор должны предусмотреть необходимые атрибуты и дополнительные сущности по необходимости. И четко представлять бизнес-задачу которую будет решать эта структура данных.
Делаем декомпозицию и нормализацию. В качестве сделанной ДЗ принимается pdf с начальной и конечной моделью.
Решая данное ДЗ вы тренируете навык проектирования БД, выделения сущностей и их атрибутов, построения связей, нормализации данных
В качестве модели была принята поставка единичного оборудования (например бытовой техники, запчастей, единиц оружия). Производство продукции не привязано к производителю, но каждый единичный товар имеет сериальный номер.
Таблицы отношений:
Таблица | Назначение |
---|---|
vendors | производители оборудования |
dealers | поставщики оборудования |
dealers2vendors | связь поставщики - производители |
description | характеристики с описаниями |
stock | товары на складе |
categories | категории товаров |
product | карточка товара (интернет магазина) |
product2description | связь товаров с их характеристиками |
orders | заказы |
order2product | связь заказы - товары |
payments | платежи |
users | пользователи |
Корректируем типы данных в модели при необходимости Взять свою структуру данных из ДЗ-1 и прописать комментарии на каждое поле с пояснением почему выбран данный тип поля и на сколько он удовлетворяет поставленной задаче
Attributes | ||||||
Name | Type | Not Null | PK | FK | Default | Comment |
---|---|---|---|---|---|---|
id_vendor | INT(11) | Yes | Yes | No | Идентификатор производителя в таблице | |
vend_name | VARCHAR(125) | Yes | No | No | Название производителя | |
vend_address | VARCHAR(255) | Yes | No | No | Адрес производителя |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
PRIMARY | ['`id_vendor`'] | PRIMARY | Индекс на ключевое поле |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
id_vendor_idx | ['`id_vendor`'] | UNIQUE | Индекс на внешний ключ |
Attributes | ||||||
Name | Type | Not Null | PK | FK | Default | Comment |
---|---|---|---|---|---|---|
id_categ | INT(11) | Yes | Yes | Yes | Идентификатор категории товара, первичный ключ. Тип INT самый подходящий. | |
name_categ | VARCHAR(45) | Yes | No | No | Имя категории. Взят универсальный формат для текста. Длина произвольная. | |
perent_id_categ | INT(11) | No | No | Yes | Внешний ключ ссылается на какое-либо занчение из этой же таблицы, которое является родительским в иерархии категорий. |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
PRIMARY | ['`id_categ`'] | PRIMARY | Индекс на ключевое поле |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
parent_id_categ_idx | ['`id_categ`', '`perent_id_categ`'] | INDEX | Индекс на внешний ключ |
Attributes | ||||||
Name | Type | Not Null | PK | FK | Default | Comment |
---|---|---|---|---|---|---|
id_dealer | INT(11) | Yes | Yes | No | Идентификатор поставщика в таблице | |
dealer_name | VARCHAR(45) | Yes | No | No | Имя поставщика | |
dealer_adress | VARCHAR(255) | Yes | No | No | Адрес поставщика |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
PRIMARY | ['`id_dealer`'] | PRIMARY | Индекс на ключевое поле |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
id_dealer_idx | ['`id_dealer`'] | INDEX | Индекс на внешний ключ |
Attributes | ||||||
Name | Type | Not Null | PK | FK | Default | Comment |
---|---|---|---|---|---|---|
id_product | INT(11) | Yes | Yes | No | Идентификатор продукта в таблице | |
id_categ | INT(11) | No | No | Yes | Идентификатор категории | |
product_name | VARCHAR(45) | No | No | No | Имя продукта | |
price | DECIMAL(10,4) | No | No | No | Цена продажи |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
PRIMARY | ['`id_product`'] | PRIMARY | Индекс на ключевое поле |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
id_categ_idx | ['`id_categ`'] | INDEX | Индекс на внешний ключ |
Attributes | ||||||
Name | Type | Not Null | PK | FK | Default | Comment |
---|---|---|---|---|---|---|
id_dealer | INT(11) | Yes | Yes | Yes | Идентификатор поставщика | |
id_vendor | INT(11) | Yes | Yes | Yes | Идентификатор производителя | |
data_start | DATETIME | No | No | No | Дата начала отношений Дилер-Вендор | |
data_end | DATETIME | No | No | No | Дата завершения отношений Дилер-Вендор |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
id_dealer_idx | ['`id_dealer`'] | INDEX | Индекс на внешний ключ |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
id_vendor_idx | ['`id_vendor`'] | INDEX | Индекс на внешний ключ |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
PRIMARY | ['`id_vendor`', '`id_dealer`'] | PRIMARY |
Attributes | ||||||
Name | Type | Not Null | PK | FK | Default | Comment |
---|---|---|---|---|---|---|
id_stock | INT(11) | Yes | Yes | No | Идентификатор записи в таблице | |
id_date | DATE | Yes | No | No | Статус единицы товара на складе | |
id_dealer | INT(11) | No | No | Yes | ||
id_vendor | INT(11) | Yes | No | Yes | Внешний ключ модель | |
item_serial_num | VARCHAR(45) | No | No | No | Сериальный уникальный номер единцы товара | |
item_cost | DECIMAL(10,4) | Yes | No | No | Закупочная цена поставщика | |
id_categ | INT(11) | No | No | Yes | Идентфикатор категории - Внешний ключ | |
reserve_sold | ENUM('1', '2', '3', '4') | No | No | No | Статус 1-резерв, 2- продано, 3 - неисправно, 4 - выставочный образец | |
id_product | INT(11) | No | No | Yes |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
PRIMARY | ['`id_stock`'] | PRIMARY | Индекс на ключевое поле |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
id_categ_idx | ['`id_categ`'] | INDEX | Индекс на внешний ключ |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
id_product_idx | ['`id_product`'] | INDEX |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
id_dealer_idx | ['`id_dealer`'] | INDEX |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
id_vendor_idx | ['`id_vendor`'] | INDEX |
Attributes | ||||||
Name | Type | Not Null | PK | FK | Default | Comment |
---|---|---|---|---|---|---|
id_description | INT(11) | Yes | Yes | Yes | Идентификатор характеристики | |
id_product | INT(11) | Yes | Yes | Yes | Идентификатор продукта |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
PRIMARY | ['`id_description`', '`id_product`'] | PRIMARY |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
id_product_idx | ['`id_product`'] | INDEX |
Attributes | ||||||
Name | Type | Not Null | PK | FK | Default | Comment |
---|---|---|---|---|---|---|
id_description | INT(11) | Yes | Yes | No | Идентификатор характеристики в таблице | |
description_name | VARCHAR(45) | Yes | No | No | Название характеристики | |
description_vol | VARCHAR(255) | No | No | No | Значение или описание характеристики |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
PRIMARY | ['`id_description`'] | PRIMARY | Индекс на ключевое поле |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
id_description_idx | ['`id_description`'] | INDEX |
Attributes | ||||||
Name | Type | Not Null | PK | FK | Default | Comment |
---|---|---|---|---|---|---|
id_user | INT(11) | Yes | Yes | No | Идентификация пользователя (покупателя) | |
name | VARCHAR(45) | Yes | No | No | Имя пользователя | |
lastname | VARCHAR(45) | Yes | No | No | Фамилия пользователя | |
birthdate | DATE | Yes | No | No | Дата рождения пользователя | |
login | VARCHAR(45) | Yes | No | No | Логин для входа на сайт | |
hash_pass | VARCHAR(45) | Yes | No | No | Хэш пароля |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
PRIMARY | ['`id_user`'] | PRIMARY | Индекс на ключевое поле |
Attributes | ||||||
Name | Type | Not Null | PK | FK | Default | Comment |
---|---|---|---|---|---|---|
id_order | INT(11) | Yes | Yes | No | Идентификатор заказа в таблице | |
order_number | VARCHAR(45) | Yes | No | No | Номер заказа в бухгалтерской системе компании | |
date | DATE | Yes | No | No | Дата заказа | |
id_user | INT(11) | Yes | No | Yes | Идентификатор покупателя |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
PRIMARY | ['`id_order`'] | PRIMARY | Индекс на ключевое поле |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
order_user_idx | ['`id_user`'] | INDEX | Индекс на внешний ключ |
Attributes | ||||||
Name | Type | Not Null | PK | FK | Default | Comment |
---|---|---|---|---|---|---|
id_order | INT(11) | Yes | Yes | Yes | Идентификатор заказа в таблице | |
id_product | INT(11) | Yes | Yes | Yes | Идентификатор продукта | |
qty | INT(11) | Yes | No | No | Количество единиц продукта |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
id_product_idx | ['`id_product`'] | INDEX | Индекс на внешний ключ |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
id_order_idx | ['`id_order`'] | INDEX | Индекс на внешний ключ |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
PRIMARY | ['`id_order`', '`id_product`'] | PRIMARY |
Attributes | ||||||
Name | Type | Not Null | PK | FK | Default | Comment |
---|---|---|---|---|---|---|
id_payments | INT(11) | Yes | Yes | No | Идентификатор платежа в таблице | |
transaction_id | INT(21) | Yes | No | No | Идентификатор транзакции в платежной системе | |
datetime | DATETIME | Yes | No | No | Дата время транзакции | |
id_order | INT(11) | Yes | No | Yes | Идентификатор заказа | |
sum | INT(11) | Yes | No | No | Сумма платежа | |
currency | VARCHAR(25) | Yes | No | No | Валюта платежа |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
PRIMARY | ['`id_payments`'] | PRIMARY | Индекс на ключевое поле |
Attributes | |||
Name | Columns | Type | Description |
---|---|---|---|
id_order_idx | ['`id_order`'] | INDEX | Индекс на внешний ключ |
Описываем логику транзакций для своей модели данных В вашем проекте базы данных опишите транзакцию, которая будет включать в себя несколько действий и исключать возможность взаимных блокировок и неоднозначных ситуаций
Описание должно включать в себя
- бизнес задачу
- вероятные проблемы
- SQL транзакции или возможно нескольких транзакций
Бизнес-задача 1. Перемещение товара в корзину электронного магазина.
Помещаем выбранный товар в корзину, и одновременно резервируем единицу товара на складе, если товара не хватает, то откатываем.
START TRANSACTION;
INSERT INTO orders (order_number, date, id_user) VALUES();
INSERT INTO order2product (id_order, id_product, qty) VALUES();
UPDATE stock SET reserve_sold="1" WHERE id_item=id_model;
COMMIT;
Бизнес-задача 2. Оплата товара.
Платим за товар и одновременно ожидаем подтверждения об оплате от платежной системы, ждем подтверждения определенное время. Если приходит положительный ответ, то все нормально, если отрицательный или превышен тайм-аут, то откатываем.
START TRANSACTION;
INSERT INTO payments (datime, id_order, sum, currency) VALUES();
--Если приходит положительный ответ, то все нормально, если отрицательный или превышен тайм-аут, то откатываем.
COMMIT;
Бизнес-задача 3. Проверка цены продажи и закупочной цены.
Получаем товар на склад по закупочной цене N и одноверменно проверяем по какой цене мы продаем товар, чтобы не поставить цену себе убыток.
START TRANSACTION;
--Получаем товар на склад по закупочной цене N и одноверменно проверяем по какой цене мы продаем товар, чтобы не поставить цену себе убыток.
COMMIT;
Бизнес-задача 4. Массовая процедура вставки в таблицу товары (stocks).
Последовательно делаем вставки новых товаров в таблицу stock. Мы хотим чтобы эта операция выполнилась одним действием.
START TRANSACTION;
INSERT INTO stock (id_dealer2vendor, id_date, id_model, item_serial_num, item_cost) VALUES();
INSERT INTO stock (id_dealer2vendor, id_date, id_model, item_serial_num, item_cost) VALUES();
INSERT INTO stock (id_dealer2vendor, id_date, id_model, item_serial_num, item_cost) VALUES();
INSERT INTO stock (id_dealer2vendor, id_date, id_model, item_serial_num, item_cost) VALUES();
...
COMMIT;
Добавляем в модель данных дополнительные индексы и ограничения
1. Проводим анализ возможных запросов\отчетов\поиска данных.
2. Предполагаем возможную кардинальность поля.
3. Создаем дополнительные индексы - простые или композитные.
4. На каждый индекс пишем краткое описание зачем он нужен (почему по этому полю\полям).
5. Думаем какие логические ограничения в БД нужно добавить - например какие поля должны быть уникальны, в какие нужно добавить условия, чтобы не нарушить бизнес логику. Пример - нельзя провести операцию по переводу средств на отрицательную сумму.
6. Создаем ограничения по выбранным полям.
Доработка проекта
С учетом всех пройденных занятий доработать свой проект до финального представления
В проекте должны быть:
- схема
- документация
- примеры бизнес-задач которые решает база
- рекомендации к использованию репликации
- рекомендации к резервному копированию
Создаем базу из проектной модели
В рамках этого домашнего задания вы сможете писать скрипт создания БД и разворачивать свой дев проект в докере
Создаем Dockerfile
в котором разворачивается image нужной СУБД
и скриптом разворачивается структура вашего проекта
наружу должен быть прокинут порт для подключения
формат сдачи - github репозиторий
в README должно быть описано как подключится к вашей базе (субд, название базы, логин, пароль, порт)
** для учебной базы сделать скрипт для партиционирования таблицы CDR по месяцам (на выходе SQL скрипт на модерацию + дамп измененной структуры)
*** проанализировать базу voip и создать внешние ключи (скрипт для создания ключей + схема данных)*
Создаем скрипты очистки и первичного заполнения базы
Наполняем свою базу данными!!
1. Запросы на встравку данных INSERT VALUES
2. Запросы на insert с использованием Select
3. Изменение данных UPDATE, UPDATE с использованием JOIN
4. Delete
*5. Процедура со вставкой и обновлением блока *
6. Merge – потренироваться и прочувствовать
формат сдачи - расширяем докерфайл - который при старте поднимает базу с данными
SQL выборка
Рассчитываем стоимость звонка в БД voip
*Строим Select для выборки всех звонков *
*поля для связи *
CDR.src_ip -> oper_ip.IP_OP
oper_ip.OP_ID -> SITE.ID
SITE.rate_o -> RATES.RATE_ID
RATES.DEST_ID -> DEST_CODES.CODE_ID
RATES.price - цена
*DEST_CODES.CODE. - код направления *
необходимо учитывать дату звонка, дату действия тарифа и дату действия IP оператора
*В oper_ip также могут быть дублирующие IP. в том числе и по дате (есть условия по префиксу номера и ip ceрвера) - *
для облегчения задачи можно вытащить уникальные записи в отдельную таблицу oper_ip_tmp
** сделать выборку с учетом префикса номера в oper_ip*
Критерии оценки: 4 - студент старался, SQL пишет но корректный запрос построить не удалось
5 - все сделано
*6 - выполнено задание со **