Come eseguire un INNER JOIN su più colonne


168

Sto lavorando a un progetto di compiti a casa e dovrei eseguire una query del database che trova i voli in base al nome della città o al codice dell'aeroporto, ma la flightstabella contiene solo i codici dell'aeroporto, quindi se voglio cercare per città devo unisciti al airportstavolo.

La tabella degli aeroporti ha le seguenti colonne: code, city
La tabella dei voli ha le seguenti colonne: airline, flt_no, fairport, tairport, depart, arrive, fare
Le colonne fairporte tairportsono i codici da e per aeroporto.
Le colonne departe arrivesono le date di partenza e di arrivo.

Ho trovato una domanda che prima unisce i voli sulla fairportcolonna e sulla airports.codecolonna. Affinché io possa abbinare il tairportdevo eseguire un altro join sulle partite precedenti dal primo join.

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

La mia query restituisce i risultati corretti e sarà sufficiente ai fini dei compiti, ma mi chiedo se posso JOINsu più colonne? Come costruirò la WHEREclausola in modo che corrisponda alla partenza e alla città / codice di destinazione?

Di seguito è una "pseudo-query" su ciò che voglio raggiungere, ma non riesco a ottenere correttamente la sintassi e non so come rappresentare la airportstabella per le partenze e le destinazioni:

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

Aggiornare

Ho trovato anche questa rappresentazione visiva di SQL Iscriviti dichiarazioni di essere molto utile come guida generale su come costruire istruzioni SQL!


3
Suggerimento: è necessario cercare due città per ogni record (una per il fairport e l'altra per il tairport. È quindi OK (effettivamente necessario) avere due JOIN, con la tabella degli aeroporti, ma una basata sul fairport l'altra in aeroporto
mjv

2
Suggerimento2: dovrai quindi anche alias la tabella degli aeroporti in modo da sapere come differenziarli (ovvero quale è la tabella degli aeroporti con la ricerca fairport e con la ricerca tairport). La parola chiave SQL per alias è AS (anche se può essere omessa, ovvero ... UNISCITI agli aeroporti [AS] FA ON FA.code = flights.tairport ...)
mjv

Risposte:


141

È possibile ISCRIVERSI con la stessa tabella più di una volta dando un alias alle tabelle unite , come nell'esempio seguente:

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

Si noti che gli alias to_porte from_portsono per la prima e la seconda copia della airportstabella.


OK, ho provato la soluzione precedente e ho visualizzato il seguente errore: Si è verificato un errore nella sintassi SQL; controlla il manuale corrispondente alla versione del tuo server MySQL per la sintassi corretta da usare vicino a 'INNER_JOIN aeroporti to_port ON (to_port.code = flights.tairport) DOVE' alla riga 7
Kiril

2
OH, so perché :) dovrebbe essere INNER JOIN non INNER_JOIN ... DOH!
Kiril

21
Se la tabella degli aeroporti è enorme, è meglio unirla una sola volta a più condizioni. Qualcosa del genere - flights f INNER JOIN airports a ON a.code = f.fairport OR a.code = f.tairportPer favore, suggerisci.
Ankur-m,

26

qualcosa di simile a....

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
L'ho chiesto sopra, ho pensato che lo chiederò anche qui - Se la tabella degli aeroporti è enorme (E c'è più filtro per l'intera query utilizzando la condizione WHERE), è meglio unirlo solo una volta a più condizioni. Qualcosa del genere: flights f INNER JOIN airports a ON a.code = f.fairport OR a.code = f.tairportfa qualche differenza? Cosa ne pensi?
Ankur-m,

1
Fa differenza per i risultati, il primo produce una fila per volo con da e a, il tuo suggerimento produrrebbe 2 file per volo, una fila con il da e una con l'aeroporto. Tuttavia, sarebbe più veloce aderire solo una volta.
Paul Creasey,

19

se mysql è ok per te:

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

modifica: esempio aggiunto per filtrare l'output per codice o città


11

Puoi semplicemente usare e nella clausola on?

Ad esempio, qualcosa del tipo:

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)

5
Come diavolo è arrivato a 14 voti positivi? L'istruzione non è corretta sia nella sintassi che nel significato.
ultracrepidario,

3

Se vuoi cercare su entrambi gli aeroporti DA e TO, ti consigliamo di unirti due volte alla tabella Aeroporti, quindi puoi utilizzare sia da che verso le tabelle nel tuo set di risultati:

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
 ...
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.