Я часто видел таблицы line_item для заказов или счетов-фактур, которые копируют одно или несколько полей из других таблиц, чтобы сделать моментальный снимок заказа клиента, когда он был размещен.
Однако в моей схеме я могу создать представление заказа без копирования данных. Поэтому поиск данных по заказу / товару / цене немного дороже, но я экономлю время, пространство и избыточность при копировании / вставке. Я понимаю, что копирование / вставка является одноразовой транзакцией, тогда как поиск потребуется много раз - однако я имею дело только с 10 тысячами записей в данной таблице, и я не ожидаю, что производительность будет проблема.
Итак, а) моя схема поддерживает точный поиск без снимка, и б) у меня нет острой необходимости в поисковой оптимизации, я думаю, что имеет смысл запустить расчет вместо того, чтобы делать снимок. Или я что-то упускаю, и мне всегда нужно делать снимок в подобных случаях?
Вот пример того, как будет выглядеть расчет поиска:
# display order items for a particular order on a particular date
# get order, products and base prices from order_id
order_products = SELECT * FROM order_has_product ohp
INNER JOIN price ON (price.product_id = ohp.product_id)
INNER JOIN order ON (order.id = ohp.order_id)
WHERE order_id = ?
# calculate price of each product at order.datetime_opened
for op in order_products:
tax = SELECT SUM(tax.rate) FROM product_has_tax pht
INNER JOIN tax ON (tax.id = pht.tax_id)
WHERE pht.product_id = op.product_id
AND tax.date_start <= op.datetime_opened
AND tax.date_end >= op.datetime_opened
discount_product = SELECT SUM(discount.rate) FROM product_has_discount phd
INNER JOIN discount ON (discount.id = phd.discount_id)
WHERE phd.product_id = op.product_id
AND discount.date_start <= op.datetime_opened
AND discount.date_end >= op.datetime_opened
discount_customer = SELECT SUM(discount.rate) FROM customer_has_discount chd
INNER JOIN discount ON (discount.id = chd.discount_id)
WHERE chd.customer_id = op.customer_id
AND discount.date_start <= op.datetime_opened
AND discount.date_end >= op.datetime_opened
AND (chd.date_used_limited IS NULL OR chd.date_used_limited = op.datetime_opened)
discount = discount_product + discount_customer
price = op.price * (1-discount) * (1+tax)