搜索行程表的路线

时间:2018-12-06 23:18:21

标签: sql sql-server algorithm

情况

我们正在实施一项搜索,您可以在其中搜索计划,从何处去。

定义

  1. 如果往返于马赫的时间表很容易,并且所有停靠点都将退回
  2. 如果从和要精确匹配一条腿,则仅返回该腿
  3. 如果from和to位于不同的腿上,则会返回这两条腿,也许是两条腿之间的腿

数据库架构

时间表
  • ID(主键)
  • 名称
  • ID(主键)
  • Origin_ID(外键)
  • 目的地ID(外键)
  • Schedule_ID(计划表的外键)
  • ETD(ISO 8601日期字符串)
  • ETA(ISO 8601日期字符串)

示例

时间表:

|---------|--------------|--------------|
|    ID   |    Origin    | Destination  |
|---------|--------------|--------------|
|    1    |  Airport A   |  Airport B   |
|---------|--------------|--------------|
|    2    |  Airport B   |  Airport C   |
|---------|--------------|--------------|
|    3    |  Airport C   |  Airport D   |
|---------|--------------|--------------|
|    4    |  Airport D   |  Airport E   |
|---------|--------------|--------------|
|    5    |  Airport E   |  Airport F   |
|---------|--------------|--------------|
  • 第1个人想从 X座机场转到 Y座机场
    • 没有结果
  • 第2个人想从机场A 转到机场F
    • 返回整个时间表
  • 第3个人想从机场B 转到机场C
    • 只有腿2的返回时间表
  • 第4个人想从机场C 转到机场F
    • 第3、4和5条腿的返回时间表
  • 第5个人想从机场D 转到机场B
    • 没有结果

伪代码

  1. 查找时间表

    SELECT
        ScheduleID AS ID
    FROM
        Leg
    WHERE
        ScheduleID IN (
            SELECT
                ScheduleID
            FROM
               Leg
            WHERE
                Leg.Origin_ID = from AND
                ETD > DateAdd(day, -1, getUTCDate())
        ) AND
        Leg.Destination_ID = to
    GROUP BY
        ScheduleID, ETD
    ORDER BY
        ETD
    
  2. 获取时间表的依据

    SELECT
        convert(char(20), Leg.ETD AT TIME ZONE 'UTC', 127) AS ETD,
        convert(char(20), Leg.ETA AT TIME ZONE 'UTC', 127) AS ETA,
        Leg.Origin_ID, Leg.Destination_ID, Leg.ScheduleID, Leg.ID
    FROM
        Leg
    INNER JOIN
        Schedule ON Schedule.ID = Leg.ScheduleID
    WHERE
        Leg.ScheduleID IN (<!-- IDs from query above -->)
    ORDER BY
        Leg.ScheduleID, Leg.ETD
    
  3. 过滤适用的支腿

    var res = [];
    loop over 2nd query group="Schedule_ID"
        var start = false;
        var end = false;
        var currentSchedule = {
            'id': Schedule_ID,
            'legs': []
        };
        inner loop
            if (Origin_ID is from) {
                currentSchedule.legs.push(ID);
                currentSchedule['etd'] = ETD;
                start = true;
            }
    
            if (start) {
                if (not currentSchedule.legs.includes(ID)) {
                    currentSchedule.legs.push(ID);
                }
                if (Destination_ID is to) {
                   currentSchedule['eta'] = ETA;
                }
            }
    res.push(currentSchedule);
    

问题

此代码有效,但是我对结果代码有些不满意。我想知道是否有一种方法可以重构代码,从而减少步骤,减少循环,从而使调试更快,更好。

有什么建议吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

第一个查询返回的腿在fromto上都完全匹配,您无需在同一张表上使用内部IN (SELECT...)。只需直接过滤Leg

SELECT
    ScheduleID AS ID
FROM
    Leg
WHERE
    Origin_ID = from
    AND ETD > DateAdd(day, -1, getUTCDate())
    AND Destination_ID = to
GROUP BY
    ScheduleID, ETD
ORDER BY
    ETD

第二个查询看起来还可以。

代码的第三部分对我来说真的没有意义。