如何存储旧数据,这是正确的方法吗?
Posted
技术标签:
【中文标题】如何存储旧数据,这是正确的方法吗?【英文标题】:How to store old data, and is this the correct way? 【发布时间】:2019-05-22 13:16:15 【问题描述】:问题:存储带有日期的 start_price。价格可以多次更改,并且还应该存储价格更改的原因。
除了制作价格变化表之外,我想不出其他方法吗?
CREATE TABLE price (
start_price decimal(4,2) NOT NULL,
price_date timestamp,
PRIMARY KEY (start_price, price_date)
);
CREATE TABLE pricechange (
start_price decimal(4,2) NOT NULL,
new_price decimal(4,2) NOT NULL,
price_date date NOT NULL,
reason varchar(100),
FOREIGN KEY (start_price, price_date)
REFERENCES price(start_price, price_date)
);
我在 pricechange 表中收到错误,我也不知道如何实际使用 sql 将价格从 price 存储到 pricechange 并将新价格存储为价格。
例如 price = 100。newprice = 50 原因:太贵了。应该是这样的:
价格表: 当前价格:50 price_date:价格创建的时间戳
价格变化: 起始价格:100 新价格:50 日期:价格变化的时间戳 原因:太贵了
【问题讨论】:
您需要在pricechange
中为更改日期设置一个单独的列,您不能为此使用price_date
,因为它是 FK 的一部分
次要点...您的价格列使用decimal(4,2)
,其范围为-99.99 到+99.99,即您的示例中100 的价格对于定义的列来说太大而无法存储!跨度>
【参考方案1】:
一个包含price
、effective_from
和reason
列的表怎么样。然后你可以使用一个视图显示current_prices
使用一点点狡猾!
CREATE TABLE product_prices (
product_id int NOT NULL
, effective_date datetime NOT NULL DEFAULT Current_Timestamp
, price decimal(4,2) NOT NULL
, reason varchar(400) NOT NULL
, CONSTRAINT pk_product_prices PRIMARY KEY (product_id, effective_date)
, CONSTRAINT fk_product_prices_products FOREIGN KEY (product_id) REFERENCES products (product_id)
);
CREATE VIEW current_product_prices
AS
SELECT product_prices.product_id
, product_prices.price
FROM product_prices
INNER
JOIN (
SELECT product_id
, Max(effective_date) AS max_effectve_date
FROM product_prices
WHERE effective_date <= Current_Timestamp
GROUP
BY product_id
) AS current_price_date
ON current_price_date.product_id = product_prices.product_id
AND current_price_date.max_effectve_date = product_prices.effective_date
;
这是空代码(即概念性和未经测试的),因为我不在可以运行 mysql 的地方。
...但它应该是说明性的(足够)!
【讨论】:
@GordonLinoff - 以什么方式?现在刚刚在一个 MySQL 实例上测试了一下,看起来很开心…… 。 .这很奇怪。视图的from
子句中通常不允许子查询。这可能是一种真正的痛苦。【参考方案2】:
从价格变化表开始,因为那是你真正需要的:
create table price_changes (
price_change_id int auto_increment primary key,
start_price decimal(4,2) NOT NULL,
new_price decimal(4,2) NOT NULL,
price_date date NOT NULL,
reason varchar(100)
);
您只需在此表中插入新价格。
然后您可以使用触发器维护表current_prices
。或者,如果您愿意,也可以选择视图:
create view price_date, current_price as
select pc.new_price as price
from price_changes pc
order by change_date desc
limit 1;
【讨论】:
【参考方案3】:我不同意其他答案(到目前为止)。我怀疑您的示例已简化和/或随着时间的推移会变得更加复杂。因此,查询会变得混乱和/或缓慢。
我建议 2 张桌子。将一个视为“当前”,将一个视为“历史”。每当价格发生变化时,history
将 INSERTed
更新为 current
。我会借助TRIGGER
在应用代码或存储过程或中执行这两个步骤。
根据将应用于每个表的查询来设计每个表的列。在您发现需要它们之前,不要考虑FOREIGN KEYs
。请记住,这两个表可能永远不会在同一个查询中使用。
【讨论】:
以上是关于如何存储旧数据,这是正确的方法吗?的主要内容,如果未能解决你的问题,请参考以下文章