简体   繁体   English

SQL表设计 - 存储行程的多个分支

[英]SQL Table Design - Storing multiple legs of a trip

I want to create a database to store the legs of a trip, where each leg has a FK in another table the trip identifier will be the key/unique. 我想创建一个数据库来存储行程的分支,其中每个分支在另一个表中具有FK,行程标识符将是密钥/唯一。

Eg "'East coast roadtrip': Boston -> NYC, NYC -> Philly, Philly -> Baltimore, Baltimore -> DC, DC -> Raleigh" 例如“'东海岸自驾游':波士顿 - >纽约,纽约 - >费城,费城 - >巴尔的摩,巴尔的摩 - > DC,DC - >罗利”

Later on, I would like the run queries such as, 稍后,我想运行查询,如,

"Which trips contain the NYC -> Philly and Philly -> Baltimore legs?"

I am a bit stumped as to how to effectively store such trip information. 关于如何有效地存储这样的旅行信息,我有点难过。 A trip identifier key and storing the trip legs as a plain text column probably isn't the most efficient solution. 行程标识符密钥并将行程支路存储为纯文本列可能不是最有效的解决方案。

Would appreciate any tips on how to approach this. 非常感谢有关如何处理此问题的任何提示。

It sounds rather simple. 听起来很简单。

You want a trip table, with a trip_id, perhaps a label such as "East coast roadtrip", perhaps dates, who took the trip, departure date/time, or whatever. 你想要一个旅行表,有一个trip_id,也许是一个标签,如“东海岸自驾游”,也许是日期,参加旅行,出发日期/时间等等。

You probably want a node table, to store the cities ("Boston", "Philly", etc) or whatever places are your begin and end points of each leg. 你可能想要一个节点表来存储城市(“波士顿”,“费城”等),或者你的每条腿的起点和终点。 So this would contain a node_id and its name or label. 所以这将包含node_id及其名称或标签。

Each leg of the trip joins two nodes. 旅程的每一段都加入了两个节点。 You want a trip_leg table, containing the trip_id, from_node_id, and to_node_id. 你想要一个trip_leg表,包含trip_id,from_node_id和to_node_id。 You might possibly want other info here such as date/time arrival at your destination. 您可能想要其他信息,例如到达目的地的日期/时间。

  SELECT t.label
    FROM trips as t
    INNER JOIN trip_legs as x1  ON (t.trip_id = x1.trip_id)
    INNER JOIN trip_legs as x2  ON (t.trip_id = x2.trip_id 
                                AND x1.to_node_id = x2.from_node_id)
    WHERE x1.from_node_id IN (SELECT node_id FROM nodes WHERE name = "NYC")
      AND x1.to_node_id   IN (SELECT node_id FROM nodes WHERE name = "Philly")
      AND x2.to_node_id   IN (SELECT node_id FROM nodes WHERE name = "Baltimore")

I would create the following: 我会创建以下内容:

A Location Table which has each location possible and an ID value 具有可能的每个位置的位置表和ID值

CREATE TABLE Location(
    LocationID int NOT NULL AUTO_INCREMENT,
    Location nchar(10) NOT NULL,
    PRIMARY KEY 
(LocationID) 
);

A Leg Table which includes each leg of the trip. 腿表包括旅行的每一段。 It has an ID for the Leg with a Location ID for both the Origin and Destination which act as a foreign key to the Location Table 它具有Leg的ID,其Origin和Destination的位置ID充当Location Table的外键

CREATE TABLE Leg(
    LegID int NOT NULL AUTO_INCREMENT,
    Origin int NOT NULL,
    Destination int NOT NULL,
PRIMARY KEY(LegID) 
);

FOREIGN KEY(Origin) REFERENCES Location(LocationID)

FOREIGN KEY(Destination) REFERENCES Location(LocationID)

A Trip table which contains each Leg of the Trip and is a Trip ID and basic details: 一个旅行表,其中包含旅行的每个腿,并且是旅行ID和基本细节:

CREATE TABLE Trip(
    TripID int NOT NULL AUTO_INCREMENT,
PRIMARY KEY (TripID)
);

A TripLeg table which joins the Trip and Leg details with a TripID and LegID 一个TripLeg表,它将Trip和Leg细节与TripID和LegID连接起来

CREATE TABLE TripLeg(
    LegID int NOT NULL,
    TripID int NOT NULL,
PRIMARY KEY (LegID ,TripID)
);

FOREIGN KEY(LegID) REFERENCES Leg(LegID)
FOREIGN KEY(TripID) REFERENCES Trip(TripID)

This will allow you to query based on city, individual leg or total trip. 这将允许您根据城市,个人腿或总旅行进行查询。 Hope this helps. 希望这可以帮助。

Assuming your trips are not "one offs" but instead are conducted on predetermined lines (and a single line can generate multiple trips), then you'll need something like this: 假设你的旅行不是“一次性”,而是在预定的线路上进行(并且一条线路可以产生多次旅行),那么你需要这样的东西:

在此输入图像描述

(If they are one-offs, just imagine LINE is the trip.) (如果他们一次性的,想象一下LINE就是这次旅行。)

Pay attention to the structure of LEG: 注意LEG的结构:

  • Its PK contains LEG_NO, but doesn't contain STOP_ID: the LEG_NO determines the order of legs in the given line, and also allows multiple legs to traverse the same stop, if necessary (eg on a round-trip). 它的PK包含LEG_NO,但不包含STOP_ID:LEG_NO确定给定行中的腿的顺序,并且如果需要(例如,在往返行程中)还允许多个腿穿过相同的停止点。
  • Also, there is only "starting" (and not "ending") stop in the leg - whatever is the "previous" (as defined by LEG_NO) leg determines the starting stop for the next leg. 此外,腿部只有“开始”(而不是“结束”)停止 - 无论“前一个”(由LEG_NO定义),腿确定下一个腿的起始停止。 This way, you can never have the disconnected legs (ie where previous leg's ending stop doesn't match next leg's starting stop). 通过这种方式,您可以永远不会断开连接的腿(即前一条腿的结束位置与下一条腿的起始位置不匹配)。

The TRIP's PK contains TRIP_NO instead of (for example) START_DATE_TIME, to allow multiple trips to be started on the same line at the same time, should you ever need that. TRIP的PK包含TRIP_NO而不是(例如)START_DATE_TIME,以允许同时在同一行开始多次旅行,如果您需要的话。

A 23-rd trip on your example 'East coast roadtrip' line could be represented like this: 您的示例“东海岸公路”线上的第23次旅行可以表示如下:

TRIP: LINE_ID  TRIP_NO
      -------  -------
          100       23

LINE: LINE_ID  LINE_NAME
      -------  ---------
          100  'East coast roadtrip'

LEG:  LINE_ID  LEG_NO  STOP_ID
      -------  ------  -------
          100       1       55
          100       2       11
          100       3       66
          100       4       22
          100       5       44
          100       6       33

STOP: STOP_ID  STOP_NAME
      -------  ---------
           22  'Baltimore'
           11  'NYC'
           33  'Raleigh'
           66  'Philly'
           55  'Boston'
           44  'DC'

(NOTE: I intentionally used non-sequential numbers to flesh-out the connections more clearly.) (注意:我故意使用非连续数字来更清楚地充实连接。)


With this database structure, you can easily get trips that went through all of the given stops, for example: 使用此数据库结构,您可以轻松获得经历了所有给定停靠点的行程,例如:

SELECT *
FROM TRIP
WHERE
    LINE_ID IN (
        SELECT LINE_ID
        FROM LEG JOIN STOP ON LEG.STOP_ID = STOP.STOP_ID
        WHERE STOP_NAME IN ('NYC', 'Philly', 'Baltimore')
        GROUP BY LINE_ID
        HAVING COUNT(DISTINCT STOP_ID) = 3
    )

(NOTE: On older versions of MySQL, you'd want to rewrite this query as JOIN due to the problems query optimizer had with IN.) (注意:在旧版本的MySQL上,由于查询优化器对IN的问题,您希望将此查询重写为JOIN。)

However, if you want to get trips that went through these stops in that order and with no "gaps" in-between, thighs get hairy in a hurry. 但是,如果你想按照这个顺序进行这些停留的旅行并且两者之间没有“间隙”,那么大腿就会匆匆而过。 Probably your best bet is to get the results of the sub-query above and analyze them client-side, rather than trying to establish the order and detect gaps in SQL (which is fundamentally set-based). 可能你最好的办法是获取上面的子查询结果并在客户端分析它们,而不是试图建立顺序并检测SQL中的差距(基本上是基于集合的)。

Have a trip table, which has a 1:many relationship with leg . 有一个trip桌,与leg有1:多的关系。 The leg will contain to and from foreign keys to location . 专家组将包含tofrom外键location

You can then do your query by doing a SELECT from as many leg s as you like, each one being aliased as a different name, and ensuring that they all have the same trip_id . 然后,您可以做一个做你的查询SELECT从尽可能多的leg S作为你喜欢,每个人被别名为一个不同的名称,并确保它们都具有相同的trip_id

Maybe something like: 也许是这样的:

SELECT
    trip.name
FROM
    trip
    INNER JOIN leg leg1 ON (trip.id = leg1.trip_id)
    INNER JOIN leg leg2 ON (trip.id = leg2.trip_id)
    INNER JOIN location location_from1 ON (
        location_from1.id = leg1.location_from_id
    )
    INNER JOIN location location_to1 ON (
        location_to1.id = leg1.location_to_id)
    )
    INNER JOIN location location_from2 ON (
        location_from2.id = leg2.location_from_id
    )
    INNER JOIN location location_to2 ON (
        location_to2.id = leg2.location_to_id
    )
WHERE
    location_from1.name = 'NYC'
    AND location_to1.name = 'Philly'
    AND location_from2.name = 'Philly'
    AND location_to2.name = 'Baltimore'

All those extra location joins are expensive however, so you may wish to look up the primary keys for your various locations before this query, and then you can just add your WHERE clauses to the leg tables. 但是,所有这些额外的位置连接都很昂贵,因此您可能希望在此查询之前查找各个位置的主键,然后您可以将WHERE子句添加到leg表中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM