2022-02-18 22:03:35
设计MySQL数据库支持PHP每周自动开奖的抽奖活动,需围绕用户参与资格、订单数据、奖池管理、开奖记录等核心需求构建表结构,并通过定时任务与SQL逻辑实现自动化流程。 以下是具体设计方案:
一、数据库表结构设计用户表 (users)
字段:
user_id (INT, 主键, 自增):用户唯一标识。
username (VARCHAR(50)):用户名。
total_orders (INT):用户累计下单次数(用于入围资格判断)。
last_order_date (DATE):用户最近下单日期(辅助统计周期内数据)。
作用:存储用户基础信息及参与抽奖的资格数据。
订单表 (orders)
字段:
order_id (INT, 主键, 自增):订单唯一标识。
user_id (INT, 外键关联users.user_id):下单用户ID。
order_date (DATE):下单日期(用于筛选周期内订单)。
order_amount (DECIMAL(10,2)):订单金额(用于奖金加权分配)。
作用:记录用户订单详情,作为抽奖资格和奖金计算的依据。
抽奖活动表 (raffles)
字段:
raffle_id (INT, 主键, 自增):活动唯一标识。
start_date (DATE):活动开始日期(每周一)。
end_date (DATE):活动结束日期(每周日)。
total_prize_pool (DECIMAL(12,2)):本期奖池总金额(含滚动资金)。
status (ENUM('pending', 'active', 'completed')):活动状态(待开奖、进行中、已完成)。
作用:管理每期抽奖活动的时间范围和奖池资金。
奖品表 (prizes)
字段:
prize_id (INT, 主键, 自增):奖品唯一标识。
raffle_id (INT, 外键关联raffles.raffle_id):所属活动ID。
prize_name (VARCHAR(100)):奖品名称。
prize_quantity (INT):奖品数量。
prize_value (DECIMAL(10,2)):单个奖品价值(用于固定奖品分配)。
作用:定义每期活动的奖品类型及数量(若奖品固定,可简化逻辑;若按奖金分配,可仅记录奖品名称)。
获奖用户表 (winners)
字段:
winner_id (INT, 主键, 自增):获奖记录唯一标识。
raffle_id (INT, 外键关联raffles.raffle_id):所属活动ID。
user_id (INT, 外键关联users.user_id):获奖用户ID。
winning_amount (DECIMAL(10,2)):用户获奖金额(按订单金额比例分配)。
prize_id (INT, 外键关联prizes.prize_id, 可为空):关联的奖品ID(若奖品固定)。
作用:记录每期活动的获奖用户及奖金分配结果。
统计上周入围用户
SQL逻辑:UPDATE users uJOIN ( SELECT user_id, COUNT(*) AS weekly_orders FROM orders WHERE order_date BETWEEN DATE_SUB(raffles.end_date, INTERVAL 7 DAY) AND raffles.end_date GROUP BY user_id HAVING weekly_orders > 0 -- 至少下单一次入围) o ON u.user_id = o.user_idSET u.total_orders = o.weekly_orders;
说明:筛选上周(end_date - 7天至end_date)内有订单的用户,更新其total_orders字段为周期内下单次数。
计算总下单金额与奖池滚动
总下单金额:SELECT SUM(order_amount) AS total_amountFROM ordersWHERE order_date BETWEEN DATE_SUB(raffles.end_date, INTERVAL 7 DAY) AND raffles.end_date;
奖池滚动:-- 获取上一期奖池50%滚动至本期INSERT INTO raffles (start_date, end_date, total_prize_pool, status)VALUES (DATE_ADD(raffles.end_date, INTERVAL 1 DAY), DATE_ADD(raffles.end_date, INTERVAL 7 DAY), (SELECT total_prize_pool * 0.5 FROM raffles WHERE raffle_id = LAST_INSERT_ID() - 1), 'pending');
说明:新一期活动开始时,奖池初始金额为上一期剩余的50%,剩余50%保留至本期奖池。
分配奖金与记录获奖用户
按订单金额比例分配奖金:INSERT INTO winners (raffle_id, user_id, winning_amount)SELECT r.raffle_id, o.user_id, (o.order_amount / total.total_amount) * r.total_prize_pool * 0.5 AS winning_amountFROM orders oJOIN ( SELECT SUM(order_amount) AS total_amount FROM orders WHERE order_date BETWEEN DATE_SUB(r.end_date, INTERVAL 7 DAY) AND r.end_date) totalJOIN raffles r ON r.status = 'active'WHERE o.order_date BETWEEN DATE_SUB(r.end_date, INTERVAL 7 DAY) AND r.end_dateGROUP BY o.user_id;
说明:根据用户订单金额占周期内总金额的比例,分配本期奖池的50%奖金。
发放奖品(需额外逻辑)
固定奖品分配:若奖品为固定类型(如“一等奖1名,二等奖3名”),需在prizes表中预定义奖品数量,并通过PHP逻辑随机抽取获奖用户。
奖金兑换奖品:若奖品为虚拟商品或需用户自主选择,可通过winning_amount字段记录奖金,用户兑换时扣减库存(需额外库存管理表)。
每周日22:00触发以下操作:
锁定相关表(防止并发修改)。
执行统计入围用户、计算奖金、分配奖品等SQL逻辑。
更新raffles表状态为completed,并生成新一期活动记录。
解锁表并记录操作日志。
通过上述设计,MySQL数据库可高效支持PHP实现的每周自动开奖抽奖活动,确保数据准确性与流程自动化。