Jak wykonać INNER JOIN na wielu kolumnach

168

Pracuję nad projektem domowym i mam wykonać zapytanie do bazy danych, które wyszuka loty według nazwy miasta lub kodu lotniska, ale flightstabela zawiera tylko kody lotnisk, więc jeśli chcę szukać według miasta, muszę dołączyć do airportsstołu.

Tabela lotnisk zawiera następujące kolumny: code, city
Tabela lotów zawiera następujące kolumny: airline, flt_no, fairport, tairport, depart, arrive, fare
Kolumny fairporti tairportto kody lotnisk od i do .
Kolumny departi arrivesą datami wyjazdu i przyjazdu.

Wpadłem z zapytaniem, które najpierw łączy loty na fairportkolumnie i airports.codekolumnie. Aby dopasować połączenie, tairportmuszę wykonać inne złączenie na poprzednich meczach z pierwszego złączenia.

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 = '?')

Moje zapytanie zwraca prawidłowe wyniki i wystarczy do zadania domowego, ale zastanawiam się, czy mogę JOINw wielu kolumnach? Jak skonstruować WHEREklauzulę, aby pasowała do miejsca wylotu i miasta / kodu docelowego?

Poniżej znajduje się „pseudo-zapytanie” dotyczące tego, co chcę osiągnąć, ale nie mogę poprawnie uzyskać składni i nie wiem, jak przedstawić airportstabelę odlotów i miejsc docelowych:

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')

Aktualizacja

Zauważyłem również, że ta wizualna reprezentacja instrukcji SQL Join jest bardzo pomocna jako ogólny przewodnik dotyczący konstruowania instrukcji SQL!

Kiril
źródło
3
Wskazówka: Musisz wyszukać dwa miasta dla każdego rekordu (jedno dla portu lotniczego, a drugie dla tairport. Dlatego jest OK (rzeczywiście potrzebne), aby mieć dwa JOINY z tabelą lotnisk, ale jedno z nich oparte na fairport, drugie na lotnisku
mjv
2
Podpowiedź 2: w związku z tym musisz również aliasować tabelę lotnisk, aby wiedzieć, jak je rozróżnić (tj. Która jest tablicą lotniska z wyszukiwaniem portów lotniczych i wyszukiwaniem portów lotniczych). Słowem kluczowym SQL dla aliasu jest AS (chociaż można je pominąć, np. ... DOŁĄCZ do lotnisk [AS] FA ON FA.code = loty.tairport ...)
mjv

Odpowiedzi:

141

Możesz DOŁĄCZAĆ do tej samej tabeli więcej niż raz, nadając połączonym tabelom alias , jak w poniższym przykładzie:

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='?'

Zauważ, że to_porti from_portsą aliasami dla pierwszej i drugiej kopii airportstabeli.

Daniel Vassallo
źródło
OK, wypróbowałem powyższe rozwiązanie i pojawił się następujący błąd: Masz błąd w składni SQL; sprawdź instrukcję, która odpowiada Twojej wersji serwera MySQL, aby znaleźć właściwą składnię do użycia w pobliżu „INNER_JOIN lotniska to_port ON (to_port.code = flight.tairport) WHERE” w linii 7
Kiril
2
OH, wiem dlaczego :) to ma być INNER JOIN, a nie INNER_JOIN ... DOH!
Kiril
21
Jeśli tabela lotnisk jest ogromna, lepiej dołączyć do niej tylko raz pod kilkoma warunkami. Coś w stylu - flights f INNER JOIN airports a ON a.code = f.fairport OR a.code = f.tairportproszę o sugestię.
Ankur-m
26

coś jak....

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
Paul Creasey
źródło
1
Zadałem to powyżej, myśl spytam również tutaj - Jeśli tabela lotnisk jest ogromna (ORAZ jest więcej filtru do całego zapytania przy użyciu warunku WHERE), czy lepiej jest dołączyć do niej tylko raz pod wieloma warunkami. Coś w stylu - flights f INNER JOIN airports a ON a.code = f.fairport OR a.code = f.tairportczy to ma znaczenie? Co myślisz?
Ankur-m
1
To ma znaczenie dla wyników, pierwsza generuje jeden wiersz na lot z i do, twoja sugestia utworzyłaby 2 rzędy na lot, jeden wiersz z lotniskiem i jeden z lotniskiem. Szybciej byłoby jednak dołączyć tylko raz.
Paul Creasey,
19

jeśli mysql jest dla Ciebie w porządku:

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: dodany przykład filtrowania danych wyjściowych dla kodu lub miasta

Phil Rykoff
źródło
12

Czy możesz po prostu użyć i w klauzuli on?

Na przykład coś takiego:

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
źródło
4
Jak to się stało, że otrzymało 14 głosów pozytywnych? Oświadczenie jest niepoprawne zarówno pod względem składni, jak i znaczenia.
ultracrepidarian
3

Jeśli chcesz wyszukiwać zarówno na lotniskach OD, jak i DO, zechcesz dwukrotnie dołączyć do tabeli Lotniska - wtedy możesz użyć zarówno tabel od, jak i do w swoim zestawie wyników:

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
źródło