如果我在products
表格中添加新产品或更改数据,它会自动添加到products_history
。这是通过触发器完成的。
当客户下订单时,无需在order_products
表中复制产品名称。
要从order_products
表中获取产品名称和价格,您将从products_history
表中查询而不是products
表
注意:我正在展示简单的演示表。
请参阅下表和结果:
mysql> select * from products;
+----+------------+-------+---------------------+
| id | name | price | timestamp |
+----+------------+-------+---------------------+
| 1 | Product 63 | 2.00 | 2011-10-08 18:55:53 |
| 2 | Product 42 | 3.00 | 2011-10-08 18:55:44 |
+----+------------+-------+---------------------+
mysql> select * from products_history;
+----+------------+-------+---------------------+
| id | name | price | timestamp |
+----+------------+-------+---------------------+
| 1 | Product 23 | 2.00 | 2011-10-08 18:55:44 |
| 2 | Product 42 | 3.00 | 2011-10-08 18:55:44 |
| 1 | Product 63 | 2.00 | 2011-10-08 18:55:53 |
+----+------------+-------+---------------------+
订单表:
mysql> select * from `order`;
+----+-------------+
| id | total_price |
+----+-------------+
| 1 | 9999.00 |
+----+-------------+
mysql> select * from order_products;
+----+----------+------------+---------------------+
| id | order_id | product_id | product_timestamp |
+----+----------+------------+---------------------+
| 1 | 1 | 2 | 2011-10-08 18:55:44 |
| 2 | 1 | 1 | 2011-10-08 18:55:53 |
+----+----------+------------+---------------------+
从订单表中获取产品名称和价格:
SELECT order.total_price, products_history. * FROM `order`
LEFT JOIN order_products ON order_products.order_id = order.id
LEFT JOIN products_history ON products_history.id = order_products.product_id
AND products_history.timestamp = order_products.product_timestamp
WHERE order.id =1
结果:
+-------------+------+------------+-------+---------------------+
| total_price | id | name | price | timestamp |
+-------------+------+------------+-------+---------------------+
| 9999.00 | 2 | Product 42 | 3.00 | 2011-10-08 18:55:44 |
| 9999.00 | 1 | Product 63 | 2.00 | 2011-10-08 18:55:53 |
+-------------+------+------------+-------+---------------------+
似乎工作正常。
这个设计中是否有任何重大缺陷,或者我可以采取哪些不同的方式?
关于Extras的第二个问题......产品可以有额外的或没有额外的。我是否需要为extra_group
表格进行版本化?我只对extra
表进行了版本控制。
请参阅下表:
mysql> select * from extra_group;
+----+------------------+
| id | name |
+----+------------------+
| 1 | Extras Group One |
+----+------------------+
mysql> select * from extras;
+----+---------+-------+---------------------+
| id | name | price | timestamp |
+----+---------+-------+---------------------+
| 1 | Extra 1 | 0.30 | 2011-10-08 18:57:55 |
| 2 | Extra 2 | 2.31 | 2011-10-08 18:58:10 |
+----+---------+-------+---------------------+
mysql> select * from extras_history;
+----+---------+-------+---------------------+
| id | name | price | timestamp |
+----+---------+-------+---------------------+
| 1 | Extra 1 | 0.30 | 2011-10-08 18:57:55 |
| 2 | Extra 2 | 2.30 | 2011-10-08 18:57:55 |
| 2 | Extra 2 | 2.31 | 2011-10-08 18:58:10 |
+----+---------+-------+---------------------+
mysql> select * from products_extras;
+----+------------+----------------+
| id | product_id | extra_group_id |
+----+------------+----------------+
| 1 | 2 | 1 |
+----+------------+----------------+
//This mean Product ID 2 have extras from extra_group_id = 1
附加订单表:
mysql> select * from order_products_extras;
+-------------------+----------+---------------------+
| order_products_id | extra_id | extra_timestamp |
+-------------------+----------+---------------------+
| 1 | 1 | 2011-10-08 18:57:55 |
| 1 | 2 | 2011-10-08 18:58:10 |
+-------------------+----------+---------------------+
//客户从product_id 1中选择了extra_id 1和2
使用类似的查询来获取extras_history
表
触发器:
CREATE TRIGGER `extras-afterinsert` AFTER INSERT ON `extras`
FOR EACH ROW BEGIN
INSERT INTO `extras_history` VALUES (NEW.`id`, NEW.`name`, NEW.`price`, NEW.`timestamp`);
END
|
CREATE TRIGGER `extras-afterupdate` AFTER UPDATE ON `extras`
FOR EACH ROW BEGIN
INSERT INTO `extras_history` VALUES (NEW.`id`, NEW.`name`, NEW.`price`, NEW.`timestamp`);
END
与products_history
表类似。
我是否在浪费时间使用历史表,我是否应该将名称/价格复制到order_products
和order_products_extras
表中?
注意:procucts和extras表中将有超过100,000行...每天超过1000个订单。
答案 0 :(得分:0)
仅记录单个时间戳的一个危险是很难确定给定订单的最新条目。您必须使用子选择或函数。我建议使用start_timestamp和finish_timestamp,后者对于最新的条目为NULL。当一个条目成为历史时,它会填充其finish_timestamp。还有其他方法可以解决这个问题,我确定,但在我看来这是最直接的。
答案 1 :(得分:0)
我真的无法理解你想用历史表来实现什么。如果产品价格快速变化并且您想在当前时间保存产品基价,为什么不将其放入order_product?
orders :
order_id / created_at / status (PK : order_id)
order_products :
order_id / product_id / quantity / product_price (PK : order_id, product_id)
这样您就不必每次都加入product_history。你可以为额外的东西做同样的非规范化。
P.S:尽量不要在表/列名中使用“order”之类的保留字,它可能会引入错误。