Как сделать INNER JOIN на нескольких столбцах

168

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

Таблица аэропортов имеют следующие столбцы: code, city
Таблица полетов имеют следующие столбцы: airline, flt_no, fairport, tairport, depart, arrive, fare
Столбцы fairportи tairportявляется от и до кодов аэропортов.
Столбцы departи arriveявляются даты вылета и прилета.

Я пришел с запросом, который сначала объединяет полеты в fairportстолбце и airports.codeстолбце. Для того, чтобы я соответствовал, tairportя должен выполнить еще одно объединение на предыдущих матчах с первого.

SELECT airline, flt_no, fairport, tairport, depart, arrive, fare
    FROM (SELECT * FROM flights
        INNER JOIN airports
        ON flights.fairport = airports.code
        WHERE (airports.code = '?' OR airports.city='?')) AS matches
    INNER JOIN airports
    ON matches.tairport = airports.code
    WHERE (airports.code = '?' OR airports.city = '?')

Мой запрос возвращает правильные результаты, и этого будет достаточно для домашней работы, но мне интересно, могу ли я использовать JOINнесколько столбцов? Как мне составить WHEREпункт, чтобы он соответствовал пункту назначения и городу / коду пункта назначения?

Ниже приведен «псевдопросмотр» того, что я хочу получить, но я не могу правильно получить синтаксис и не знаю, как представить airportsтаблицу для отправлений и пунктов назначения:

SELECT * FROM flights
INNER JOIN airports
ON flights.fairport = airports.code AND flights.tairport = airports.code
WHERE (airports.code = 'departureCode' OR airports.city= 'departureCity') 
    AND (airports.code = 'destinationCode' OR airports.city = 'destinationCity')

Обновить

Я также нашел это визуальное представление SQL Присоединяйтесь к отчетности , чтобы быть очень полезным в качестве общего руководства о том , как построить операторы SQL!

Кирил
источник
3
Подсказка: вам нужно искать два города для каждой записи (один для Fairport, а другой для Tairport. Поэтому нормально (действительно необходимо) иметь два JOIN, с таблицей аэропортов, но один из них основан на Fairport, а другой - в аэропорту.
MJV
2
Подсказка 2: поэтому вам необходимо также создать псевдоним таблицы аэропортов, чтобы вы знали, как их дифференцировать (т. Е. Это таблица аэропортов с поиском в Fairport и поиском в Tairport). Ключевое слово SQL для псевдонима - AS (хотя оно может быть опущено, то есть ... ПРИСОЕДИНИТЬСЯ к аэропортам [AS] FA ON FA.code = tickets.tairport ...)
mjv

Ответы:

141

Вы можете присоединиться к одной и той же таблице более одного раза, указав псевдоним объединенным таблицам , как в следующем примере:

SELECT 
    airline, flt_no, fairport, tairport, depart, arrive, fare
FROM 
    flights
INNER JOIN 
    airports from_port ON (from_port.code = flights.fairport)
INNER JOIN
    airports to_port ON (to_port.code = flights.tairport)
WHERE 
    from_port.code = '?' OR to_port.code = '?' OR airports.city='?'

Обратите внимание, что to_portи from_portявляются псевдонимами для первой и второй копий airportsтаблицы.

Даниэль Вассалло
источник
ОК, я попробовал описанное выше решение и выдал следующую ошибку: у вас ошибка в синтаксисе SQL; проверьте руководство, соответствующее вашей версии сервера MySQL, на предмет правильного синтаксиса для использования рядом с 'INNER_JOIN airports to_port ON (to_port.code = flight.tairport) WHERE' в строке 7
Кирилл
2
О, я знаю почему :) это должно быть INNER JOIN, а не INNER_JOIN ... DOH!
Кирилл
21
Если таблица аэропортов огромна, лучше присоединиться к ней только один раз при нескольких условиях. Что-то вроде - flights f INNER JOIN airports a ON a.code = f.fairport OR a.code = f.tairportпожалуйста, предложите.
Анкур-м
26

что-то вроде....

SELECT f.*
      ,a1.city as from
      ,a2.city as to
FROM flights f
INNER JOIN airports a1
ON f.fairport = a1. code
INNER JOIN airports a2
ON f.tairport = a2. code
Пол Криси
источник
1
Я спрашивал об этом выше, подумал, что спросит и здесь: если таблица аэропортов огромна (И есть еще фильтр для всего запроса с использованием условия WHERE), лучше присоединиться к нему только один раз при нескольких условиях. Что-то вроде - flights f INNER JOIN airports a ON a.code = f.fairport OR a.code = f.tairportэто имеет значение? Что вы думаете?
Анкур-м
1
Это имеет значение для результатов: первый производит один ряд на рейс с и до, ваше предложение будет производить 2 строки на рейс, один ряд с от и один до аэропорта. Хотя было бы быстрее присоединиться только один раз.
Пол Криси
19

если mysql в порядке для вас:

SELECT flights.*, 
       fromairports.city as fromCity, 
       toairports.city as toCity
FROM flights
LEFT JOIN (airports as fromairports, airports as toairports)
ON (fromairports.code=flights.fairport AND toairports.code=flights.tairport )
WHERE flights.fairport = '?' OR fromairports.city = '?'

edit: добавлен пример для фильтрации вывода по коду или городу

Фил Рыкофф
источник
11

Вы можете просто использовать и в предложении on?

Например, что-то вроде:

SELECT 
   airline, flt_no, fairport, tairport, depart, arrive, fare
FROM 
   flights
INNER JOIN 
   airports from_port ON (from_port.code = flights.fairport)
   and (to_port.code = flights.tairport)
ez33
источник
5
Как же это дошло до 14 голосов? Это утверждение неверно как по синтаксису, так и по смыслу.
ультракрепидарианец
3

Если вы хотите выполнять поиск как в аэропортах FROM, так и в аэропортах TO, вам нужно будет дважды присоединиться к таблице «Аэропорты» - тогда вы можете использовать таблицы «из» и «в» в своем наборе результатов:

SELECT
   Flights.*,fromAirports.*,toAirports.*
FROM
   Flights
INNER JOIN 
   Airports fromAirports on Flights.fairport = fromAirports.code
INNER JOIN 
   Airports toAirports on Flights.tairport = toAirports.code
WHERE
 ...
MisterZimbu
источник