Cómo hacer una UNIÓN INTERNA en varias columnas

168

Estoy trabajando en un proyecto de tarea y se supone que debo realizar una consulta en la base de datos que encuentre vuelos, ya sea por el nombre de la ciudad o el código del aeropuerto, pero la flightstabla solo contiene los códigos del aeropuerto, así que si quiero buscar por ciudad, tengo que únete en la airportsmesa.

La tabla de aeropuertos tiene las siguientes columnas: code, city
la mesa de vuelos tiene las siguientes columnas: airline, flt_no, fairport, tairport, depart, arrive, fare
Las columnas fairporty tairportson los de y a códigos de aeropuertos.
Las columnas departy arriveson las fechas de salida y llegada.

Se me ocurrió una consulta que primero une los vuelos en la fairportcolumna y la airports.codecolumna. Para que coincida tairport, tengo que realizar otra unión en las coincidencias anteriores desde la primera unión.

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

Mi consulta devuelve los resultados adecuados y será suficiente para la tarea, pero me pregunto si puedo JOINen varias columnas. ¿Cómo construiría la WHEREcláusula para que coincida con la ciudad / código de salida y de destino?

A continuación se muestra una "pseudoconsulta" sobre lo que quiero lograr, pero no puedo obtener la sintaxis correctamente y no sé cómo representar la airportstabla para las salidas y los 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')

Actualizar

¡También encontré que esta representación visual de las instrucciones SQL Join es muy útil como guía general sobre cómo construir instrucciones SQL!

Kiril
fuente
3
Sugerencia: es necesario buscar dos ciudades para cada registro (una para el puerto de feria y la otra para el puerto de embarque. Por lo tanto, está bien (de hecho es necesario) tener dos UNIONES, con la tabla de aeropuertos, pero una de ellas basada en el puerto de feria, la otra en tairport.
mjv
2
Sugerencia2: por lo tanto, también deberá alias la tabla de aeropuertos para que sepa cómo diferenciarlos (es decir, cuál es la tabla de aeropuerto con la búsqueda de puerto y con la búsqueda de puerto). La palabra clave SQL para alias es AS (aunque puede omitirse, es decir ... UNIRSE a aeropuertos [AS] FA ON FA.code = vuelos.tairport ...)
mjv

Respuestas:

141

Puede UNIRSE a la misma tabla más de una vez dando un alias a las tablas unidas , como en el siguiente ejemplo:

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

Tenga en cuenta que to_porty from_portson alias para la primera y segunda copia de la airportstabla.

Daniel Vassallo
fuente
De acuerdo, probé la solución anterior e hice el siguiente error: Tiene un error en su sintaxis SQL; consulte el manual que corresponde a la versión de su servidor MySQL para obtener la sintaxis correcta para usar cerca de 'INNER_JOIN airports to_port ON (to_port.code = vuelos.tairport) WHERE' en la línea 7
Kiril
2
OH, sé por qué :) se supone que es INNER JOIN no INNER_JOIN ... DOH!
Kiril
21
Si la tabla de aeropuertos es enorme, ¿es mejor unirse solo una vez con múltiples condiciones? Algo así como - flights f INNER JOIN airports a ON a.code = f.fairport OR a.code = f.tairportPor favor sugiéralo.
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
fuente
1
Lo he preguntado anteriormente, también lo preguntaré aquí: si la tabla de aeropuertos es enorme (Y hay más filtros para toda la consulta con la condición WHERE), ¿es mejor unirse solo una vez con múltiples condiciones? Algo así como: flights f INNER JOIN airports a ON a.code = f.fairport OR a.code = f.tairport¿hace alguna diferencia? ¿Qué piensas?
Ankur-m
1
Hace una diferencia en los resultados, el primero produce una fila por vuelo con from y to, su sugerencia produciría 2 filas por vuelo, una fila con from y una con el aeropuerto. Sin embargo, sería más rápido unirse solo una vez.
Paul Creasey
19

si mysql está bien para ti:

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

editar: ejemplo agregado para filtrar la salida por código o ciudad

Phil Rykoff
fuente
11

¿Puedes usar y en la cláusula on?

Por ejemplo, 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
fuente
55
¿Cómo demonios llegó esto a 14 votos a favor? La declaración es incorrecta tanto en sintaxis como en significado.
ultracrepidarian
3

Si desea buscar en los aeropuertos FROM y TO, querrá unirse a la tabla de aeropuertos dos veces; luego puede usar las tablas from y to en su 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
fuente