Uniones entre tablas

Hasta ahora, las consultas que se han visto solamente acceden a una tabla a la vez. Sin embargo, las consultas pueden acceder a varias tablas al mismo tiempo, o acceder a la misma tabla de tal forma que se procesen varias filas al mismo tiempo. A las consultas que acceden a varias filas de la misma o de diferentes tablas a la vez se les llama consultas combinadas. Como ejemplo, digamos que se desea listar todos los registros de climas junto con la ubicación de las ciudades asociadas a ellos. Para hacerlo, es necesario comparar la columna city de cada una de las filas de la tabla weather con la columna name de todas las filas en la tabla cities y seleccionar los pares de filas donde estos valores concuerden.

Lo anterior se logra de la siguiente manera:

midb=# SELECT * FROM weather, cities WHERE city = name;

     city      | temp_lo | temp_hi | prcp |    date    |     name      | location
---------------+---------+---------+------+------------+---------------+-----------
 San Francisco |      46 |      50 | 0.25 | 1994-11-27 | San Francisco | (-194,53)
 San Francisco |      43 |      57 |    0 | 1994-11-29 | San Francisco | (-194,53)
(2 filas)

Observe dos cosas sobre el resultado:

  • No hay resultado para la ciudad “Hayward”. Esto es porque en la tabla cities no hay ninguna ciudad llamada de esa manera. Por esta razón, la unión ignora las filas sin pareja de la tabla weather. Más adelante verá cómo resolver esto.

  • Hay dos columnas que contienen el nombre de la ciudad. Esto es correcto porque la lista de columnas de las tablas weather y cities se concatenan. Sin embargo, en la práctica, esto no es deseable; así que tal vez sería mejor listar explícitamente las columnas en vez de usar *, como se muestra a continuación:

    midb=# SELECT city, temp_lo, temp_hi, prcp, date, location FROM weather, cities WHERE city = name;

En el ejemplo de arriba, como todas las columnas en las dos tablas tienen nombres diferentes, el analizador sintáctico (parser) encuentra automáticamente a qué tabla pertenece cada columna. Si hubiera nombres de columnas duplicados en las dos tablas, sería necesario especificar la tabla a la que pertenece cada columna:

midb=# SELECT weather.city, weather.temp_lo, weather.temp_hi, weather.prcp,
              weather.date, cities.location
       FROM weather, cities WHERE cities.name = weather.city;

Generalmente se considera buen estilo especificar siempre en las uniones la tabla a la que pertenece cada columna, así la consulta no fallará en caso de agregar más adelante un nombre de columna duplicado a una de las tablas.

Las consultas combinadas vistas hasta ahora también se pueden escribir de esta manera alternativa:

midb=# SELECT * FROM weather INNER JOIN cities ON (weather.city = cities.name);

Esta sintaxis no se usa tanto como la primera, pero se muestra aquí para ayudarle a entender los temas que siguen.

Ahora vamos a ver cómo incluir los registros relacionados con la ciudad “Hayward”. Lo que se desea de la consulta es que escanee la tabla weather y, para cada fila, que encuentre las filas que concuerdan con la tabla cities. Si no se encuentra concordancia, queremos que se agreguen “valores vacíos” en las columnas correspondientes a la tabla cities. Este tipo de consulta se llama combinación externa (outer join). (Las combinaciones que se han visto hasta ahora son internas o “inner joins”.) La orden sería como esta:

midb=# SELECT * FROM weather LEFT OUTER JOIN cities ON (weather.city = cities.name);

     city      | temp_lo | temp_hi | prcp |    date    |     name      | location
---------------+---------+---------+------+------------+---------------+-----------
 San Francisco |      46 |      50 | 0.25 | 1994-11-27 | San Francisco | (-194,53)
 San Francisco |      43 |      57 |    0 | 1994-11-29 | San Francisco | (-194,53)
 Hayward       |      37 |      54 |      | 1994-11-29 |               |
(3 filas)

Más específicamente, esta consulta se conoce como combinación externa izquierda (left outer join) porque la tabla mencionada a la izquierda del operador de unión tendrá sus filas en el resultado por lo menos una vez, mientras que la tabla de la derecha solo tendrá aquellas filas que concuerden con alguna fila de la tabla de la izquierda. Cuando se muestra una fila de una tabla “izquierda” para la cual no hay pareja en la tabla “derecha”, se sustituyen valores vacíos (null) para las columnas de la tabla “derecha”.

También existen combinaciones externas derechas (right outer joins) y combinaciones externas completas (full outer joins). Intente averiguar para qué sirven estas.

También es posible unir una tabla a sí misma. Esto se conoce como autocombinación (self join). Como ejemplo, suponga que se desea encontrar registros de clima que estén en el rango de temperatura de otros registros de clima. Así que se necesita comparar las columnas temp_lo y temp_hi de cada fila de la tabla weather con las columnas temp_lo y temp_hi de todas las demás filas de la tabla weather. Esto se puede hacer con la siguiente consulta:

midb=# SELECT W1.city, W1.temp_lo AS low, W1.temp_hi AS high, W2.city, W2.temp_lo AS low, W2.temp_hi AS high FROM weather W1, weather W2 WHERE W1.temp_lo < W2.temp_lo AND W1.temp_hi > W2.temp_hi;

     city      | low | high |     city      | low | high
---------------+-----+------+---------------+-----+------
 San Francisco |  43 |   57 | San Francisco |  46 |   50
 Hayward       |  37 |   54 | San Francisco |  46 |   50
(2 filas)

En el ejemplo anterior se han usado los alias W1 y W2 para la tabla, de tal forma que se puedan distinguir el lado izquierdo y derecho de la unión. También puede usar este tipo de alias en otras consultas para ahorrarse letras. Por ejemplo:

midb=# SELECT * FROM weather w, cities c WHERE w.city = c.name;

Encontrará que este estilo abreviado se usa con mucha frecuencia.

Tema anterior

Consultar tablas

Próximo tema

Funciones de agregados

Esta página