Как смоделировать реляционную базу данных, в которой хранятся детали заказа? - PullRequest
1 голос
/ 22 мая 2019

Я делаю POS-приложение для Android на базе ресторана и пытаюсь найти наилучший способ моделирования базы данных для него, используя Room ORM, который обеспечивает удобство обслуживания.Моей базе данных, помимо прочего, необходимо вести учет всех товаров, проданных в рамках транзакции / заказа, а также журнал самих заказов и список продуктов питания, продаваемых в ресторане.С учетом следующих таблиц (для краткости я включаю только столбцы, которые, по моему мнению, имеют отношение к вопросу, и, возможно, не иллюстрирую всю информацию, которая мне понадобится для каталогизации), я могу создать таблицу, которая включает в себя журнал всех когда-либо размещенных заказов, и вызывать егоall_orders:

all_orders
-----------
id (PK)
oder_details_id (FK) - referencing the PK from order_details table
date
notes
total
payment_type

Я также могу создать таблицу, содержащую все продукты питания / блюда, которые подают в ресторане, и назовем ее all_items:

all_items
---------
id (PK)
name
category
price

Никаких проблем там нетпока, но мое текущее заблуждение лежит здесь - как мне вести журнал фактических продуктов питания, проданных в рамках заказа? Один из подходов, о которых я думал, - это создать таблицу по номеру заказа, но создатьДинамические таблицы - это уже проблема, а наличие 60 000 таблиц в конце года станет кошмаром для удобства обслуживания.Поэтому мое другое возможное решение - создать таблицу с именем order_details, которая, вероятно, будет заканчиваться сотнями тысяч записей в год со следующими столбцами:

order_details
-------------
id (PK)
item_id (FK) - referencing the PK from the all_items table
order_id (FK) - referencing the PK from the all_orders table
quantity_ordered

И когда пользователь хочет получить заказ изскажем, на прошлой неделе программа может использовать запрос на соединение, который выдаст в пользовательском интерфейсе приложения следующее:

order
---------
id (PK)
date (from the all_orders table)
name (from all_items)
category (from all_items)
price (from all_items)
total (from all_orders)
payment_type (from all_orders)

Боюсь, что таблица order_details слишкомширокий, поскольку он будет содержать сотни тысяч записей, и запрос его для записей будет вялым.Я уверен, что индексация поможет, но правильный ли это подход к этой проблеме?Если нет, есть ли лучшее, лучшее решение?Если возможно, то, что фокусируется на группировании любого заказа и его элементов без единого сброса всех элементов из всех заказов в одну таблицу .Любая помощь будет принята с благодарностью.

Редактировать: Этот вопрос не является дубликатом this , и хотя эта ссылка полезна, она не предоставила дополнительного контекста относительно того, о чем я действительно спрашиваюи это не совсем относится к ответу, который я ищу.Я набросал свой последний оригинальный абзац, так как мой вопрос на самом деле о том, как я могу смоделировать вышеуказанные данные, поскольку мне неясно, основываясь на моем исследовании , как хранить фактические детали заказа, прикрепленные к заказу (многие учебные пособия / похожие вопросы, с которыми я сталкивался, не дают полного объяснения вышеупомянутому).

1 Ответ

1 голос
/ 22 мая 2019

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

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

Аналогичным образом, вам, вероятно, также нужна таблица payment_type (снова для нормализации).

Создание отдельных таблиц для заказов, вероятно, просто создаст кошмар.

Цена и общая суммаРазве они не одинаковы?Сказать, что итоговые данные могут быть получены при извлечении данных, поэтому нет необходимости хранить такую ​​информацию.

Таким образом, следующая структурная схема может быть близка к той, которую вы хотите: -

DROP TABLE IF EXISTS item;
DROP TABLE IF EXISTS category;
CREATE TABLE IF NOT EXISTS category (_id INTEGER PRIMARY KEY, category_name TEXT);

CREATE TABLE IF NOT EXISTS item (
    _id INTEGER PRIMARY KEY, 
    item_name TEXT UNIQUE, 
    category_ref INTEGER REFERENCES category(_id) ON DELETE CASCADE ON UPDATE CASCADE, 
    item_price REAL
);

DROP TABLE IF EXISTS payment_type;
CREATE TABLE IF NOT EXISTS payment_type (
    _id INTEGER PRIMARY KEY, 
    payment_type TEXT UNIQUE, 
    surcharge REAL
);

-- NOTE cannot call a table order as it is a keyword (not rea true but have to enclose the name e.g.g [order]). 
DROP TABLE IF EXISTS customer_order;
CREATE TABLE IF NOT EXISTS customer_order (
    _id INTEGER PRIMARY KEY, 
    customer_name TEXT, 
    date TEXT DEFAULT CURRENT_TIMESTAMP, 
    payment_type_ref INTEGER REFERENCES payment_type(_id) ON DELETE CASCADE ON UPDATE CASCADE
);

DROP TABLE IF EXISTS order_detail;
CREATE TABLE IF NOT EXISTS order_detail (
    customer_order_ref INTEGER REFERENCES customer_order(_id) ON DELETE CASCADE ON UPDATE CASCADE, 
    item_ref REFERENCES item(_id) ON DELETE CASCADE ON UPDATE CASCADE,
    quantity
);

Пример

Ниже приведен собственный SQL, демонстрирующий схему выше: -

Часть 1, добавление (вставка) данных: -

INSERT INTO category (category_name) VALUES
    ('Fish'),('Beef'),('Chicken'),('Lamb'),('Sea Food')
;
INSERT INTO item (item_name, item_price, category_ref) VALUES
    ('Fish and Chips',11.30,1),
    ('Steak and Kidney Pudding',15.45,2),
    ('Lamb Chops, Mashed Potato and Gravy',17.40,3)
;

INSERT INTO payment_type (payment_type, surcharge) VALUES
    ('Master Card',0.05),('Visa',0.05),('Cash',0),('American Express',0.15)
;

INSERT INTO customer_order (customer_name, payment_type_ref) VALUES
    ('Fred',3),
    ('Mary',1),
    ('Tom',2),
    ('Jane',4)
;
INSERT INTO order_detail (customer_order_ref, item_ref, quantity) VALUES
    (1,1,2),(1,2,1), -- Fred (id 1) orders 2 Fish and Chips (id 1) and 1 Steak and Kidney (id 2)
    (2,3,10), -- Mary orders 10 Lamb chops
    (3,2,1),(3,1,1),(3,3,1), -- Tom orders 1 of each
  (4,1,1) -- Just Fish and chips for Jane   
;

Часть 2 - Извлечение полезных ( возможно ) данных

Вот и пример того, чтоВы можете сделать с SQL, который включает в себя производные данные ( как предложено выше ): -

SELECT 
    customer_name, 
    date, 
    group_concat(item_name) ||'('||quantity||')' AS items, 
    sum(item_price) AS total_price, 
    payment_type, 
    round(sum(item_price) * surcharge,2) AS surcharge,
    round((sum(item_price) * surcharge) + sum(item_price),2) AS total_price
    FROM customer_order
        JOIN order_detail ON customer_order._id = order_detail.customer_order_ref
        JOIN item ON order_detail.item_ref = item._id
        JOIN payment_type ON customer_order.payment_type_ref = payment_type._id
    GROUP BY customer_order._id -- Treats all data for an order as a single row allowing the use of aggregate functions on the groups e.g. sum, group_concat
;

Результат

enter image description here

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