2013-03-23 2 views
2

Я хочу создать базу данных для хранения ножек поездки, где каждая нога имеет FK в другой таблице, идентификатор поездки будет ключевым/уникальным.SQL Table Design - Сохранение нескольких ножек поездки

E.g. " 'Восточное побережье Roadtrip': Бостон -> Нью-Йорк, Нью-Йорк -> Филли, Филли -> Балтимор, Балтимор -> DC, DC -> Raleigh"

Позже я хотел бы запросы прогонов, такие как,

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

Я немного зациклен на том, как эффективно хранить такую ​​информацию о поездке. Ключ идентификатора поездки и сохранение стоек отключения в виде столбца с обычным текстом, вероятно, не является наиболее эффективным решением.

Поблагодарили бы за какие-либо советы о том, как подойти к этому.

ответ

2

Предполагая, что ваши поездки не «один офф», но вместо этого проводятся по заранее определенным линиям (и одна линия может генерировать несколько поездок), то вам нужно что-то вроде этого:

enter image description here

(. Если они являются один-офф, только представьте себе линия поездка)

Обратите внимание на структуру Ножка:

  • Его PK содержит LEG_NO, но не содержит STOP_ID: LEG_NO определяет порядок ног в данной строке, а также позволяет нескольким ногам проходить по одной и той же остановке, если необходимо (например, в оба конца).
  • Кроме того, в ноге есть только «старт» (а не «окончание») - что бы ни было «предыдущим» (как определено LEG_NO), нога определяет начальную остановку для следующего этапа. Таким образом, у вас никогда не может быть отключенных ножек (т. Е. Когда конечная остановка предыдущего этапа не соответствует стартовой остановке следующей ноги).

Рк TRIP содержит trip_no вместо (к примеру) START_DATE_TIME, чтобы несколько поездок, чтобы быть запущен на той же линии, в то же время, если вы когда-нибудь нужно.

23-й поездки на вашем примере «Восточное побережье Roadtrip» линия может быть представлена ​​следующим образом:

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' 

(Примечание: я намеренно использовал непоследовательных номера для телесного из соединений более четко .)


С помощью этой структуры базы данных, вы можете легко получить поездки, которые прошли через все заданные упоры, например:

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 
    ) 

(Примечание: На старых версиях MySQL, вы хотите переписать этот запрос как JOIN из-за проблемы, оптимизатор запросов имели с IN.)

Однако, если вы хотите, чтобы поездки, которые пошли через эти остановки в таком порядке и без «промежутков» между ними бедра становятся волосатыми в спешке. Вероятно, лучше всего получить результаты вышеприведенного запроса и проанализировать их на стороне клиента, вместо того, чтобы пытаться установить порядок и обнаружить пробелы в SQL (который основывается на принципе).

+1

Хорошая работа, связанная с проблемой 1-> 2 и 2-> 3, не связана непосредственно. И диаграмма тоже! +1 – halfer

+0

Спасибо, Бранко, я очень ценю то время, которое вы взяли, чтобы войти в такие подробности! – r3su

1

Есть таблица trip, которая имеет отношения 1: много с leg. Нога будет содержать to и from внешних ключей до location.

Вы можете сделать запрос, выполнив SELECT из многих leg с, как вам нравится, каждая из которых состоит псевдонимами под другим именем, и гарантируя, что все они имеют один и тот же trip_id.

Может быть что-то вроде:

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' 

Все эти дополнительные места соединения являются дорогими, однако, так что вы можете посмотреть на первичные ключи для ваших различных местах, прежде чем этот запрос, а затем вы можете просто добавить свой WHERE клаузулы к столам ног.

2

Это звучит довольно просто.

Вам нужен стол для поездки с trip_id, возможно, такой ярлык, как «дорожная поездка на восточном побережье», возможно, даты, которые совершили поездку, дату/время вылета или что-то еще.

Возможно, вам нужна таблица узлов, чтобы хранить города («Бостон», «Филадельфия» и т. Д.), Или где бы вы ни начинали и заканчивали каждую ногу. Таким образом, это будет содержать node_id и его имя или метку.

Каждая нога поездки соединяет два узла. Вам нужна таблица trip_leg, содержащая trip_id, from_node_id и to_node_id. Возможно, вам понадобится другая информация, например, прибытие даты и времени в пункт назначения.

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") 
2

Я хотел бы создать следующее:

Расположение Таблица которое имеет каждое место можно и значение ID

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

окорока Таблица, которая включает в себя каждый этап поездки.Он имеет идентификатор для окорока с Location ID для обоихов происхождения и назначения, которые действуют в качестве внешнего ключа к местоположению таблице

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) 

приводится таблица поездки, который содержит каждый этап поездки и является Маршрутным идентификатором и основные детали:

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

TripLeg таблица, которая соединяет путевую и деталь 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) 

Это позволит вам запрашивать в зависимости от города, индивидуальных или ног общей тр ф. Надеюсь это поможет.

+0

Является ли это моим воображением, или это ответ TSQL на вопрос mySQL? ;-) – WarrenT

+1

Да, у меня нет mySQL, но я хочу дать вам определения таблиц, которые я буду использовать для создания базы данных. Дизайн будет таким же. – Harrison

+0

Было бы бесполезно дать эффективное решение DB2, например, поскольку я использовал бы обычные табличные выражения, недоступные в mySQL. Аналогично, многие конструкции TSQL также недоступны. – WarrenT

Смежные вопросы