Mysql 订单和子订单的数据库设计
在此之前,我根据以下信息创建了此数据库模式:一个订单有多个项目,每个项目可以属于多个订单。一个项目有一个标价,可以随时间变化。应记录客户在特定日期购买商品的价格,以便进行历史报告Mysql 订单和子订单的数据库设计,mysql,database,oracle,database-design,relational-database,Mysql,Database,Oracle,Database Design,Relational Database,在此之前,我根据以下信息创建了此数据库模式:一个订单有多个项目,每个项目可以属于多个订单。一个项目有一个标价,可以随时间变化。应记录客户在特定日期购买商品的价格,以便进行历史报告 CREATE TABLE item ( item_id INT AUTO_INCREMENT ,item_name VARCHAR(30) ,item_list_price DECIMAL(10,2) ... CONSTRAINT ... PRIMARY KEY (item_id
CREATE TABLE item (
item_id INT AUTO_INCREMENT
,item_name VARCHAR(30)
,item_list_price DECIMAL(10,2)
...
CONSTRAINT ... PRIMARY KEY (item_id)
);
CREATE TABLE `order` (
order_id INT AUTO_INCREMENT
,order_status VARCHAR(30)
,customer_id INT NOT NULL
...
,CONSTRAINT ... PRIMARY KEY (order_id)
);
CREATE TABLE order_item (
order_item_id INT AUTO_INCREMENT
,order_id INT NOT NULL
,item_id INT NOT NULL
,order_item_quantity INT
,order_item_cost DECIMAL(10,2)
,CONSTRAINT ... PRIMARY KEY (order_item_id)
,CONSTRAINT ... FOREIGN KEY (order_id) REFERENCES `order` (order_id)
,CONSTRAINT ... FOREIGN KEY (item_id) REFERENCES `item` (item_id)
);
然而,我注意到一个项可以有多个子项。例如,一个汉堡包项目可能有一个奶酪子项目,一个培根子项目,等等。据推测,每个子项目应该能够属于许多项目。奶酪可以放在汉堡包、意大利面等上。显然,不会有递归子项
实现这一点的最佳方式是什么
这里有一种不使用继承的方法。创建一个子项表和一个子项桥接表。item_子项表包含一个强制的FK to项,但包含一个可为空的FK to子项。在订单表中,链接到item_子项。这不是正确的数据库继承,但在一定程度上模仿了它
CREATE TABLE item (
item_id INT AUTO_INCREMENT
,item_name VARCHAR(30)
,item_list_price DECIMAL(10,2)
...
,CONSTRAINT ... PRIMARY KEY (item_id)
);
CREATE TABLE subitem (
subitem_id INT AUTOINCREMENT
,subitem_name VARCHAR(30)
,subitem_list_price DECIMAL(10,2)
...
,CONSTRAINT ... PRIMARY KEY (subitem_id)
);
-- Note how subitem_id is nullable
CREATE TABLE item_subitem (
item_subitem_id INT AUTO_INCREMENT
,item_id INT NOT NULL
,subitem_id INT
,CONSTRAINT ... PRIMARY KEY (item_id, subitem_id)
,CONSTRAINT ... UNIQUE (item_subitem_id)
,CONSTRAINT ... FOREIGN KEY (item_id) REFERENCS item (item_id)
,CONSTRAINT ... FOREIGN KEY (subitem_id) REFERENCES subitem (subitem_id)
);
-- Note how this bridge table between order and item_subitem links to item_subitem's unique key
CREATE TABLE order_item_subitem (
order_item_subitem_id INT AUTO_INCREMENT
,order_id INT
,item_subitem_id INT
,order_item_quantity INT
,order_item_cost DECIMAL(10,2)
,CONSTRAINT ... PRIMARY KEY (order_item_subitem_id)
,CONSTRAINT ... FOREIGN KEY (order_id) REFERENCES `order` (order_id)
,CONSTRAINT ... FOREIGN KEY (item_subitem_id) REFERENCES item_subitem (item_subitem_id)
);
这是处理这种情况的最好办法吗?什么会更好
最终用户应该能够检查其历史购买情况(记住标价将来可能会发生变化)。以下是一个订单的示例:
Order # 123456
Customer Name - Matthew Moisen
- Salad $3
- Custom
- Hamburger $5
- Cheese $1
- Bacon $1
- Apple $1
-----------------
Total $11
您所描述的是所谓的“捆绑”、“组合”或“营销套餐” 您可以销售一种产品或一包产品。您应该在这里使用抽象/继承
--using class table inheritance. postgresql syntax (sorry, but it's less verbose).
-- a product is an abstract thing you can sell, ex good, combo, service, warranty.
create table products (
product_id int primary key
);
create table goods (
product_id int primary key references products(product_id),
name text not null unique
...other good columns
);
create table bundles (
product_id int primary key references products(product_id),
name text not null unique
...other bundle columns
);
--map products to bundles:
create table bundle_products (
bundle_id int references bundles(product_id),
product_id int references products(product_id),
primary key (bundle_id, product_id)
);
您需要使用关系除法(无余数)来防止重复捆绑包。使用触发器
--order line item points at products now:
create table line_items (
order_id int references orders(order_id),
display_order smallint not null default 0,
product_id int not null references products(product_id),
quantity int not null default 1,
unit_price decimal(19,2) not null,
primary key (order_id, display_order)
);
请不要使用保留字作为表/列标识符。那样疯狂的利索拉克?MySQL?二者都请澄清。答案在某种程度上有所不同。@OllieJones我正在使用MySQL;如果我们换到另一个数据库,它将是Oracle,我也将其标记为Oracle。您可以根据需要设计一个复杂的系统,这里缺少设计的目标。只在开头提到一个简单的陈述。请说明改进设计的更多要求。比如每次订单的利润,或者销售人员的绩效分析等等。嘿,尼尔,谢谢你的回答。我很抱歉,但我应该提到一个我希望生成的报告的示例。出于订单历史记录的目的,行项目应包括捆绑名称,然后包括该项目下的所有捆绑项目以及这些捆绑项目的成本。您知道如何将其纳入您的设计吗?@MatthewMoisen您需要在
产品
和捆绑包
之间使用左外连接
,以获得捆绑包名称。您可以在mysql中使用GROUP\u CONCAT
将捆绑项目的行转换为字符串列表。您需要在捆绑项目中添加成本
列来计算成本。