Como fazer um INNER JOIN em várias colunas

168

Estou trabalhando em um projeto de lição de casa e devo executar uma consulta ao banco de dados que encontre voos pelo nome da cidade ou pelo código do aeroporto, mas a flightstabela contém apenas os códigos do aeroporto, portanto, se eu quiser pesquisar por cidade, preciso junte-se à airportsmesa.

A tabela de aeroportos possui as seguintes colunas: code, city
A tabela de vôos possui as seguintes colunas: airline, flt_no, fairport, tairport, depart, arrive, fare
As colunas fairporte tairportsão os códigos de e para o aeroporto.
As colunas departe arrivesão datas de partida e chegada.

Eu vim com uma consulta que primeiro une os vôos na fairportcoluna e na airports.codecoluna. Para que eu corresponda, tairporteu tenho que realizar outra associação nas partidas anteriores a partir da primeira associação.

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

Minha consulta retorna os resultados adequados e será suficiente para a finalidade da lição de casa, mas estou me perguntando se posso JOINem várias colunas? Como construir a WHEREcláusula para que ela corresponda à cidade / código de partida e de destino?

Abaixo está uma "pseudo-consulta" sobre o que quero obter, mas não consigo obter a sintaxe corretamente e não sei como representar a airportstabela para as partidas e os destinos:

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

Atualizar

Eu também encontrei esta representação visual do SQL Junte declarações para ser muito útil como um guia geral sobre como construir instruções SQL!

Kiril
fonte
3
Dica: você precisa procurar duas cidades para cada registro (uma para o fairport e a outra para o porto de portos. Portanto, é bom (de fato necessário) ter dois JOINs, com a tabela de aeroportos, mas um deles com base no fairport do outro em tairport.
mjv
2
Dica2: portanto, você também precisará usar o alias da tabela de aeroportos para saber como diferenciá-los (ou seja, qual é a tabela de aeroportos com a pesquisa fairport e a pesquisa tairport). A palavra-chave SQL para alias é AS (embora possa ser omitida, ou seja, ... JOIN aeroportos [AS] FA ON FA.code = flight.tairport ...)
mjv

Respostas:

141

Você pode ingressar na mesma tabela mais de uma vez, atribuindo um alias às tabelas unidas , como no exemplo a seguir:

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

Observe que os alias to_porte from_portsão para a primeira e a segunda cópias da airportstabela.

Daniel Vassallo
fonte
OK, tentei a solução acima e execute o seguinte erro: Você tem um erro na sintaxe do SQL; verifique o manual que corresponde à versão do servidor MySQL para a sintaxe correta a ser usada perto de 'INNER_JOIN aeroportos para_port ON (to_port.code = flight.tairport) WHERE' na linha 7
Kiril
2
OH, eu sei por que :) deveria ser INNER JOIN, não INNER_JOIN ... DOH!
Kiril
21
Se a tabela de aeroportos for grande, é melhor associá-la apenas uma vez com várias condições. Algo como - flights f INNER JOIN airports a ON a.code = f.fairport OR a.code = f.tairportPor favor, sugira.
Ankur-m
26

algo como....

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
fonte
1
Eu perguntei acima, o pensamento também perguntará aqui - se a tabela de aeroportos for grande (E houver mais filtro para toda a consulta usando a condição WHERE), é melhor associá-la apenas uma vez em várias condições. Algo como - flights f INNER JOIN airports a ON a.code = f.fairport OR a.code = f.tairportIsso faz alguma diferença? O que você acha?
Ankur-m
1
Faz diferença nos resultados, o primeiro produz uma linha por voo com de e para, sua sugestão produziria 2 linhas por voo, uma linha com o aeroporto de origem e outra com o aeroporto de destino. Seria mais rápido ingressar apenas uma vez.
Paul Creasey
19

se o mysql estiver correto para você:

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: exemplo adicionado para filtrar a saída para código ou cidade

Phil Rykoff
fonte
11

Você pode apenas usar e na cláusula on?

Por exemplo, algo como:

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
fonte
5
Como na Terra isso chegou a 14 votos positivos? A declaração está incorreta na sintaxe e no significado.
ultracrepidarian
3

Se você deseja pesquisar nos aeroportos FROM e TO, participará da tabela Aeroportos duas vezes - poderá usar as tabelas from e to em seu conjunto de resultados:

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
fonte