Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用rails和mysql的多下车点、目的地的机票预订算法_Mysql_Ruby On Rails_Algorithm_<img Src="//i.stack.imgur.com/RUiNP.png" Height="16" Width="18" Alt="" Class="sponsor Tag Img">elasticsearch_Graph Algorithm - Fatal编程技术网 elasticsearch,graph-algorithm,Mysql,Ruby On Rails,Algorithm,elasticsearch,Graph Algorithm" /> elasticsearch,graph-algorithm,Mysql,Ruby On Rails,Algorithm,elasticsearch,Graph Algorithm" />

使用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