php mysql购票_用PHP+MySQL实现12306购票和退票以及余票查询逻辑

车票表:

(车次, 区间, 已售)

(1024, [1,2], 0)

(1024, [1,2,3], 0)

(1024, [1,2,3,4], 0)

(1024, [2,3], 0)

(1024, [2,3,4], 0)

(1024, [3,4], 0)

主键是自增字段,给"车次"字段添加索引.

优化并发时,可以考虑根据"出发日"或"车次"进行分表分库.

区间[1,2,3]的含义是:从车站1上车,经过车站2,到车站3下车.

如果要给不同的区间配置不同的出票限额,那么可以再添加一个"限售"字段.

购票逻辑:

例如用户购买区间[2,3,4]的票时,

程序找出包含[2,3,4]的区间如[1,2,3,4]已售的票,

以及[2,3,4]包含的子区间如[2,3]和[3,4]已售的票,

如果三者的票合计小于500(这里假设列车满载为500人),

则用户能够购票,即[2,3,4]这个区间已售的票数+1.

SQL购票逻辑如下(以MySQL为例):

SET AUTOCOMMIT=0;

BEGIN WORK; --开启事务

select 已售 from 车票表 where 车次=1024

and 区间 in ('2,3,4', '2,3', '3,4', '1,2,3,4') for update;

update 车票表 set 已售=(已售+1) where 车次=1024 and 区间='2,3,4';

COMMIT WORK; --提交事务

SET AUTOCOMMIT=1;

其中 select for update 的作用是读上锁(对读出的行上写锁),依赖事务.

上述购票逻辑,关键在于找到where条件in中的区间,步骤如下:

1.找出包含一个区间如[2,3,4]的其他区间:

select 区间 from 车票表 where 车次=1024 and 区间 like '%2,3,4%';

在本例中得到:

[1,2,3,4]

2.找出一个区间如[2,3,4]里的子区间算法(以PHP为例):

function foo(array $arr, array &$tmp) {

$size = count($arr);

if($size == 1) return;

for($i=2;$i<=$size;$i++) {

$tmp[] = array_slice($arr, 0, $i);

}

array_shift($arr);

foo($arr, $tmp);

}

$arr = array(2,3,4);

$tmp = array();

foo($arr, $tmp);

var_export($tmp);

在本例中得到:

[2,3]

[2,3,4]

[3,4]

退票逻辑比购票逻辑简单得多,直接给对应车次,对应区间的已售车票-1即可:

update 车票表 set 已售=(已售-1) where 车次=1024 and 区间='2,3,4';

余票查询逻辑:

例如查询车次1024上区间[2,3,4]的余票:

select 已售 from 车票表 where 车次=1024

and 区间 in ('2,3,4', '2,3', '3,4', '1,2,3,4');

用500减去上述区间已售车票的和就是区间[2,3,4]上的余票.

这里假设列车满载为500人.

座位分配逻辑:

一列火车,其座位都是固定的,存储每列火车的座位的数据表没什么可说的.

至于座位分配,可以在车票表里增加一个"已售座位"的字段.

用户成功购票时,从"待售座位"中取一个分配给用户并更新"已售座位"字段.

"待售座位"为"所有座位"去掉相关区间"已售座位"后的座位.

SET AUTOCOMMIT=0;

BEGIN WORK; --开启事务

select 已售,已售座位 from 车票表 where 车次=1024

and 区间 in ('2,3,4', '2,3', '3,4', '1,2,3,4') for update;

update 车票表 set 已售=(已售+1), 已售座位=CONCAT(已售座位,分配座位)

where 车次=1024 and 区间='2,3,4';

COMMIT WORK; --提交事务

SET AUTOCOMMIT=1;

其中CONCAT相比直接赋值,能够减少传递给MySQL的数据. 车票表中"已售座位"字段存储"座位编号". 座位表: 座位编号, 列车, 车厢, 座位

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值