【问题标题】:Get up and down route between two stations上下两站之间的路线
【发布时间】:2021-08-03 11:15:06
【问题描述】:

我正在 laravel 中制作城市地铁列车应用程序。我有一个路线搜索功能,用户可以添加两个站点的来源和目的地,应用程序应该提供两个站点之间的适当路线。

我的表结构如下。我通过定义route_id 获得了车站之间的路线。但是,用户不会知道哪个路线 id,并且他/她想要获取路线只有两个站点。

使用这种方法,我必须定义 route_id 以使用递归查询获取路由。

寻找解决方案:

所以在这里我想找到一种方法,这样我就可以在相同的两个车站之间找到一条上下路线。例如,获取一个 从 station_id 1 到 8 以及从 station_id 8 到 1 的路线 获取 route_id 作为用户输入。

Laravel 迁移

public function up()
{
    Schema::create(
        'route_station',
        function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->bigInteger('route_id')->unsigned();
            $table->bigInteger('station_id')->unsigned();
            $table->bigInteger('next_station_id')->unsigned();
            $table->integer('station_order')->default(0);
            $table->bigInteger('interchange_id')->unsigned();
            $table->float('distance');
            $table->time('duration');
            $table->timestamps();

            $table->unique(['route_id', 'station_id'], 'route_station_unique');

            $table->foreign('route_id')
                  ->references('id')
                  ->on('routes')
                  ->onDelete('restrict');

            $table->foreign('station_id')
                  ->references('id')
                  ->on('stations')
                  ->onDelete('restrict');

            $table->foreign('next_station_id')
                  ->references('id')
                  ->on('stations')
                  ->onDelete('restrict');

            $table->foreign('interchange_id')
                  ->references('id')
                  ->on('stations')
                  ->onDelete('restrict');

        }
    );
}

数据库

+----+----------+------------+-----------------+---------------+----------------+----------+----------+
| id | route_id | station_id | next_station_id | station_order | interchange_id | distance | duration |
+----+----------+------------+-----------------+---------------+----------------+----------+----------+
|  1 |        2 |          1 |               2 |             1 |           NULL |      2.1 |      510 |
|  2 |        2 |          2 |               3 |             2 |           NULL |      1.3 |      250 |
|  3 |        2 |          3 |               4 |             3 |           NULL |      3.2 |      380 |
|  4 |        2 |          4 |               5 |             4 |           NULL |      4.5 |      725 |
|  5 |        2 |          5 |               6 |             5 |           NULL |        2 |      200 |
|  6 |        2 |          6 |               7 |             6 |           NULL |      2.7 |      270 |
|  7 |        2 |          7 |               8 |             7 |           NULL |      1.3 |      320 |
|  8 |        2 |          8 |               9 |             8 |              9 |      0.5 |      120 |
|  9 |        2 |          9 |            NULL |             9 |           NULL |      1.9 |      510 |
| 27 |        3 |          8 |               7 |             8 |           NULL |        2 |      111 |
| 28 |        3 |          7 |               6 |             7 |           NULL |        2 |      111 |
| 29 |        3 |          6 |               5 |             6 |           NULL |        2 |      111 |
| 30 |        3 |          5 |               4 |             5 |           NULL |        2 |      111 |
| 31 |        3 |          4 |               3 |             4 |           NULL |        2 |      111 |
| 32 |        3 |          3 |               2 |             3 |           NULL |        2 |      111 |
| 33 |        3 |          2 |               1 |             2 |           NULL |        2 |      111 |
| 34 |        3 |          1 |            NULL |             1 |           NULL |        2 |      111 |
+----+----------+------------+-----------------+---------------+----------------+----------+----------+

查询

SET @source = 1, @route_id = 2, @destination = 8;

WITH RECURSIVE
cte AS 
(
    SELECT `route_id`, `station_id`, `next_station_id`, `station_order`
    FROM `route_stations`
    WHERE `station_id` = @source
    AND `route_id` = @route_id
    
    UNION ALL
    
    SELECT cte.`route_id`, cte.`next_station_id`, `route_stations`.`next_station_id`, cte.`station_order` + 1
    FROM `route_stations`, cte
    WHERE `route_stations`.`station_id` = cte.`next_station_id`
        AND cte.`next_station_id` != @source
        AND cte.`station_id` != @destination
        AND `route_stations`.`route_id` = @route_id
    
)
SELECT * FROM cte
WHERE @destination = (SELECT `station_id` FROM cte ORDER BY `station_order` DESC LIMIT 1);

输出寻找

从 station_id 2 到 8

如果用户搜索source station_id 2和destination station_id为8

从 station_id 8 到 2

如果用户搜索源station_id为8,目的station_id为2

我对数据库更改持开放态度,所以如果有任何方法可以随时告诉我 制作更好的数据库结构。

【问题讨论】:

  • 以 CREATE TABLE + INSERT INTO 脚本的形式提供您的表。为此数据提供所需的结果并提供条件。
  • 我正在使用 laravel 创建一个表。插入查询正在进行中,因为我需要最终确定结构以检索路线。我将发布 laravel 迁移。
  • @Akina,我已添加您要求的信息。

标签: php mysql laravel


【解决方案1】:
Declare  @source int, @destination int, @route_id int
set @source = 2
set @destination = 8
set @route_id= case when @source<@destination then 2 else 3 end
select route_id,station_id,next_station_id,station_order from route_station where route_id = @route_id and station_id between @source and @destination and next_station_id between @source and @destination

select route_id,station_id,next_station_id,station_order from route_station where route_id = @route_id and station_id between @destination and @source and next_station_id between @destination and @source

希望你能理解这段 sql 代码。 这里如果源 id 是 lass 那么目标 id 的 route_id 设置为 2 否则 3.

这里 2 选择查询。

当您使用 sql 表值函数时,此解决方案很容易。

【讨论】:

    猜你喜欢
    • 2010-11-03
    • 2019-08-07
    • 1970-01-01
    • 1970-01-01
    • 2012-08-13
    • 1970-01-01
    • 2011-08-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多