门店关系型数据库设计优化:适配价格变更、折扣与营收统计需求
嘿,作为数据库设计新手能搞定前面三个需求已经很赞啦!针对你新增的三个价格相关需求,咱们来一步步调整现有设计,确保能完美适配:
一、需求a:追踪产品价格变更历史
现有Product表的Price字段只能存当前价格,没法追溯历史。咱们新增一张ProductPriceHistory表来记录价格变更轨迹:
表结构:
PriceHistoryID(INT, 主键, 自增):每条价格变更记录的唯一标识ProductID(VARCHAR/INT, 外键关联Product.ProductID):关联对应的产品OldPrice(DECIMAL(10,2)):变更前的旧价格NewPrice(DECIMAL(10,2)):变更后的新价格ChangeTimestamp(DATETIME):价格变更的时间ChangedBy(VARCHAR, 可选):记录操作价格变更的人员(比如管理员ID/名称)
逻辑说明:
每次修改Product表的Price字段时,先往ProductPriceHistory里插入一条记录,把旧价格、新价格和变更时间存下来。这样就能随时查询任意产品的价格变更历史,包括旧价格和变更时间啦。
查询示例:
-- 查询产品P001的所有价格变更记录 SELECT OldPrice, NewPrice, ChangeTimestamp, ChangedBy FROM ProductPriceHistory WHERE ProductID = 'P001' ORDER BY ChangeTimestamp DESC;
二、需求b:特定门店-产品的限时折扣
要实现“特定门店特定产品的限时折扣”,咱们新增一张ProductShopDiscount表,专门管理门店级别的产品折扣:
表结构:
DiscountID(INT, 主键, 自增):每条折扣规则的唯一标识ProductID(VARCHAR/INT, 外键关联Product.ProductID):关联折扣对应的产品ShopID(VARCHAR/INT, 外键关联Shop.ShopID):关联折扣适用的门店DiscountRate(DECIMAL(5,4)):折扣比例(比如0.75代表75折,1.0代表无折扣)StartTime(DATETIME):折扣生效的开始时间EndTime(DATETIME):折扣失效的结束时间IsActive(BOOLEAN, 默认TRUE):标记该折扣是否启用(方便临时关闭而不用删除记录)
逻辑说明:
比如新店开业需要给产品A设置一周8折,就往这个表插一条记录:ProductID='A'、ShopID='新店ID'、DiscountRate=0.8、StartTime=开业日期、EndTime=开业后7天。销售时判断当前时间是否在折扣有效期内,再计算实际售价。
查询示例:
-- 查询门店S001中产品P001当前生效的折扣 SELECT DiscountRate FROM ProductShopDiscount WHERE ProductID = 'P001' AND ShopID = 'S001' AND StartTime <= NOW() AND EndTime >= NOW() AND IsActive = TRUE;
三、需求c:支持查询总营收
总营收基于销售出库(History.Status='OUT')的交易计算,为了保证历史营收的准确性(避免后续价格/折扣变更影响已发生的交易),咱们调整History表:
表结构调整:
新增TransactionPrice (DECIMAL(10,2))字段,记录该笔交易发生时的实际成交价格(如果是出库交易,就是原价或折扣后的价格;入库交易可以填采购价或NULL,根据业务需求)。
逻辑说明:
当发生销售出库时,先计算当时的实际价格(优先取门店折扣后的价格,没有折扣则用产品当前价格),然后把这个价格存入TransactionPrice字段。这样计算营收时直接求和即可,不用再反向追溯历史价格/折扣,效率更高且数据准确。
查询示例:
-- 查询所有门店的总营收 SELECT SUM(Quantity * TransactionPrice) AS TotalRevenue FROM History WHERE Status = 'OUT'; -- 按门店拆分查询营收 SELECT ShopID, SUM(Quantity * TransactionPrice) AS ShopRevenue FROM History WHERE Status = 'OUT' GROUP BY ShopID;
额外优化:替换冗余的库存字段
你之前Product表的StockQuantity其实是冗余的——因为当前库存可以通过History表的出入库记录实时计算,而且更准确(避免手动更新库存导致的不一致)。建议去掉Product.StockQuantity,用下面的查询获取各门店当前库存:
SELECT ShopID, ProductID, SUM(CASE WHEN Status='IN' THEN Quantity ELSE -Quantity END) AS CurrentStock FROM History GROUP BY ShopID, ProductID;
这样调整后,你的数据库就能完美覆盖所有新需求啦!如果有业务细节需要细化,比如折扣叠加规则、价格变更的审批流程等,可以再针对性调整~
内容的提问来源于stack exchange,提问作者John




