🐡

データがないと困るのは自分だ

2025/03/07に公開

Daily Blogging76日目

システムにおいて、データの更新とか削除とかはよくある操作かなと思いますが
過去のデータがないといざという時に困っちゃうんですよね
不具合の調査の時とか

ECサイトの注文履歴の例

ユーザが注文した後に該当商品の価格を変更した場合、
後の請求の段階で変更後の価格で請求してしまい、問題になることもある

よくないパターン

-- 商品情報テーブル(価格が1つしか保持されていない場合)
CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    price DECIMAL(10, 2) NOT NULL, -- 最新価格のみ保持
    created_at TIMESTAMP DEFAULT now(),
    updated_at TIMESTAMP DEFAULT now()
);

このテーブルだと、常に最新の価格しか保持していないので過去の注文の価格にも影響を与える。

履歴を持つことで解決

製品と価格を切り離し、価格の履歴を管理する

CREATE TABLE product_price_history (
    id SERIAL PRIMARY KEY,
    product_id INT NOT NULL, 
    price DECIMAL(10, 2) NOT NULL,
    start_at TIMESTAMP NOT NULL, -- 適用開始日時
    end_at TIMESTAMP,           -- 適用終了日時
    created_at TIMESTAMP DEFAULT now()
);

注文情報のテーブルに、価格のデータを紐付ける

-- 注文テーブル(注文時の価格履歴を保持)
CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    product_id INT NOT NULL, 
    user_id INT NOT NULL,
    product_price_history_id INT NOT NULL,
    created_at TIMESTAMP DEFAULT now(),
    FOREIGN KEY (product_price_history_id) REFERENCES product_price_history(id)
);

ただこれだとデータ取得時に結合が発生してパフォーマンスに影響を与える可能性も高いので、場合によってはこっち

-- 注文テーブル(注文時の価格履歴を保持)
CREATE TABLE orders (
    id SERIAL PRIMARY KEY,
    product_id INT NOT NULL, 
    user_id INT NOT NULL,
    order_price DECIMAL(10, 2) NOT NULL, -- 注文時の価格を残す
    created_at TIMESTAMP DEFAULT now(),
);

結合がなくなるけど、データが冗長になる

Discussion