使用rails和mysql的多下车点、目的地的机票预订算法
我正在运行一个简单的一对一出发地和目的地预订服务。随着我的服务的增长,我正在考虑实施多个下车点,目的地如下使用rails和mysql的多下车点、目的地的机票预订算法,mysql,ruby-on-rails,algorithm,
elasticsearch,graph-algorithm,Mysql,Ruby On Rails,Algorithm,
elasticsearch,Graph Algorithm,我正在运行一个简单的一对一出发地和目的地预订服务。随着我的服务的增长,我正在考虑实施多个下车点,目的地如下 Routhings ----------------- id orig dest route_id denormalize_seats 1 A B 1 40 2 B C 1 40 3 C D 1 40 4 A H 2 20 A--->B
Routhings
-----------------
id orig dest route_id denormalize_seats
1 A B 1 40
2 B C 1 40
3 C D 1 40
4 A H 2 20
A--->B--->C--->D
假设一次从a(起点)到D(终点)的旅行在途中经过B和C
我的用户可以从a->B、a->C、a->D、B->C、B->D和C->D中预订座位。我的问题是找到一个好的座位可用性算法,给出一个来自
例如,B->D
我提出了一个简单的解决方案,如下所示
Routes:
-------------
id orig dest seats many_drop_off_points desc
1 A D 40 yes multiple drop-offs
2 A H 20 no straight
3 B H 12 no straight
4 A D 12 no straight
我有一个包含起点、终点的路由表。为了简单起见,我只列出了该路线的总座位数
Routes表可以有一个或多个Routing,如下所示
Routhings
-----------------
id orig dest route_id denormalize_seats
1 A B 1 40
2 B C 1 40
3 C D 1 40
4 A H 2 20
路由属于特定路由。路由可以在特定日期进行多次预订
RoutingReservation
---------------------------------
id routing_id date customer_id
通过B和C从a->D设置路线时
create in Routings table three record as shown in the table above(A->B, B->C, C->D).
如果从A->H直道未经过任何地方。
在工艺路线表中创建记录(a->H)
当客户想要从C->D中搜索路线时,我只需从一条或多条路线中搜索(复杂的计算)
预订座位也很复杂
使用路线1(多个下车点)从A->D预订10个座位
从A->C预订5个座位
Create 5 reservations from Routing 1 (from A->B)
Create 5 reservations from Routing 2 (from B->C)
从B->D预订10个座位
Create 10 seats from Routing 2 (from B->C)
Create 10 seats from Routing 3 (from C->D)
从上述3个步骤中计算路由的预订总数(复杂计算)
A->D路线的可用座位
Total - Max(total number of reservation) from A->B, B->C, C->D
40 - Max(15, 25, 20) = 15 # Route with id 1
20 - 0 = 0 # Route with id 4
A->C路线的可用座位
Total - Max(total number of reservation) from A->B, B->C
40 - Max(15, 25) = 15
B->D的可用座位
Total - Max(total number of reservation) from B->C, C->D
40 - Max(25, 20) = 15 # Route with id 1
C->D的可用座位
Total - Max(total number of reservation) from C->D
40 - Max(20) = 20 # Route with id 1
似乎可以实现这种多个下车点,但通过大量计算,目前我有30多个合作伙伴,路线超过1000条,但我想向两个合作伙伴介绍这种多个下车点作为我的起点
我正在寻找一种算法,可以更有效地解决这个问题。我当前的环境是在rubyonrails和mysql中
提前谢谢你的帮助
PS:我也对其他类型的数据存储(如ErristTyScript或MangGDB)开放。
如果您认为所有路由都有多个下拉点,只需查看简单的路由(A->B,B->C),这可能是最简单的。然后,您的数据库架构可能如下所示:
== routes table ==
id | seats | name
---|-------|------------------
1 | 10 | simple route
2 | 30 | the scenic route
== stops table ==
id | route_id | location | next_location
--------------------------------------------
1 | 1 | A | B
2 | 1 | B |
3 | 2 | A | B
4 | 2 | B | C
5 | 2 | C | D
6 | 2 | D |
== reservations table ==
// for one trip from A to B on route 1 for 5ppl
// and one trip from A to C on route 2 for 20ppl
id | route_id | start_stop_id | end_stop_id | seats_needed
------------------------------------------------------------
1 | 1 | 1 | 2 | 5
2 | 2 | 3 | 5 | 20
您会注意到,我通过添加next\u location
,对stops表进行了一点非规范化处理,该列不一定会添加任何额外信息,但会简化后续的计算
使用此模式,我们可以通过以下相当简单的查询计算(每条路线或每条可能的路段)总容量和已用容量:
robert=# SELECT routes.id as route_id, stops.id as stop_id, location, next_location,
SUM(routes.seats) as capacity,
SUM(reservations.seats_needed) as used
FROM stops
JOIN routes ON routes.id = stops.route_id
LEFT JOIN reservations
ON reservations.route_id = routes.id
AND reservations.start_stop_id <= stops.id
AND reservations.end_stop_id > stops.id
WHERE next_location IS NOT NULL
GROUP BY routes.id, stops.id
ORDER BY routes.id, location;
route_id | stop_id | location | next_location | capacity | used
----------+---------+----------+---------------+----------+------
1 | 1 | A | B | 10 | 5
2 | 3 | A | B | 30 | 20
2 | 4 | B | C | 30 | 20
2 | 5 | C | D | 30 |
robert=#选择routes.id作为route_id,stops.id作为stop_id,location,next_location,
总容量(路线、座位),
所用金额(预订。所需座位)
从头到尾
在routes.id=stops.route\u id上加入路线
左连接预订
关于reservations.route_id=routes.id
和预订。开始\停止\ id停止。id
其中next_位置不为空
按routes.id、stops.id分组
按路线订购。id、位置;
路线标识|停车标识|位置|下一个位置|通行能力|已使用
----------+---------+----------+---------------+----------+------
1 | 1 | A | B | 10 | 5
2 | 3 | A | B | 30 | 20
2 | 4 | B | C | 30 | 20
2 | 5 | C | D | 30|
此表是路线的简明表示。我们可以用它来回答更复杂的问题
因此,假设您想知道从a到D的旅程有多少个座位。此查询将查找所有此类座位,尽管它不会告诉您可以使用什么路线:
SELECT MIN(available) as available
FROM (
SELECT location, next_location, SUM(routes.seats) - COALESCE(SUM(reservations.seats_needed),0) as available
FROM stops
JOIN routes ON routes.id = stops.route_id
LEFT JOIN reservations
ON reservations.route_id = routes.id
AND reservations.start_stop_id <= stops.id
AND reservations.end_stop_id > stops.id
WHERE next_location IS NOT NULL
GROUP BY location, next_location
) availabilities
JOIN (
SELECT 'A' as a, 'B' as b
UNION ALL
SELECT 'B' as a, 'C' as b
UNION ALL
SELECT 'C' as a, 'D' as b
) legs
ON legs.a = location AND legs.b = next_location;
available
-----------
10
选择最小值(可用)作为可用值
从(
选择位置、下一个位置、总和(路线.座位)-合并(总和(需要预订.座位),0)作为可用项
从头到尾
在routes.id=stops.route\u id上加入路线
左连接预订
关于reservations.route_id=routes.id
和预订。开始\停止\ id停止。id
其中next_位置不为空
按位置分组,下一个位置
)可用性
加入(
选择“A”作为A,“B”作为B
联合所有
选择“B”作为a,“C”作为B
联合所有
选择“C”作为a,“D”作为b
)腿
腿上。a=位置和腿。b=下一个位置;
可获得的
-----------
10
现在,这是一个大量的SQL,它不能完全回答您的问题。然而,我所做的是创建一个模式来为设置的有向图建模,并演示了一些关于如何使用该有向图的查询。是的,可以用SQL进行图形计算——但正如您所看到的,特别是在上面查询中的legs
表中,有时会很麻烦。但这绝非不可能
SELECT MIN(available) as available
FROM (
SELECT location, next_location, SUM(routes.seats) - COALESCE(SUM(reservations.seats_needed),0) as available
FROM stops
JOIN routes ON routes.id = stops.route_id
LEFT JOIN reservations
ON reservations.route_id = routes.id
AND reservations.start_stop_id <= stops.id
AND reservations.end_stop_id > stops.id
WHERE next_location IS NOT NULL
GROUP BY location, next_location
) availabilities
JOIN (
SELECT 'A' as a, 'B' as b
UNION ALL
SELECT 'B' as a, 'C' as b
UNION ALL
SELECT 'C' as a, 'D' as b
) legs
ON legs.a = location AND legs.b = next_location;
available
-----------
10