如何存储旧数据,这是正确的方法吗?

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】:

一个包含priceeffective_fromreason 列的表怎么样。然后你可以使用一个视图显示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 张桌子。将一个视为“当前”,将一个视为“历史”。每当价格发生变化时,historyINSERTed 更新为 current。我会借助TRIGGER 在应用代码存储过程中执行这两个步骤。

根据将应用于每个表的查询来设计每个表的列。在您发现需要它们之前,不要考虑FOREIGN KEYs。请记住,这两个表可能永远不会在同一个查询中使用。

【讨论】:

以上是关于如何存储旧数据,这是正确的方法吗?的主要内容,如果未能解决你的问题,请参考以下文章

这是获取文件大小的正确方法吗?

iOS - 处理数据模型更改的正确方法是啥?

这是从 PHP 使用 Sphinx 的正确方法吗?

我对 PHP 会话的理解正确吗?

这是从 Firebase 检索数据的正确方法吗?

这是使用 EXISTS 的正确方法吗?