JOIN es el mecanismo que permite seleccionar columnas de dos o más tablas en un mismo SELECT, poniendo sus registros lado a lado. Usualmente, hay columnas traslapadas en cada tabla que son las que especifican el criterio de JOIN, es decir, la manera en que se construyen los nuevos registros.
Hay varias clases de JOIN. Aquí veremos sólo dos: el CROSS JOIN y el INNER JOIN. El primero entrega el producto cartesiano de las tablas. Se obtiene especificando ambas tablas en el FROM de un SELECT:
SELECT * FROM autores, institución;
autor_id | nombre | nacionalidad | fecha de nacimiento | institucion_id | institucion_id | nombre |
---|---|---|---|---|---|---|
1 | Edgser Dijkstra | Danés | 1930-05-11 | 2 | 2 | Universität Leiden |
1 | Edgser Dijkstra | Danés | 1930-05-11 | 2 | 1 | Xerox PARC |
2 | Niklaus Wirht | Suizo | 1934-02-15 | 1 | 2 | Universität Leiden |
2 | Niklaus Wirth | Suizo | 1934-02-15 | 1 | 1 | Xerox PARC |
Dado que tenemos
dos autores y dos instituciones,
el producto cartesiano
nos entrega
los cuatro cruces posibles.
Observe que hay dos columnas
llamadas
institucion_id
;
una de ellas corresponde a la
de la tabla autores
,
y la otra a la de la tabla instituciones
.
Pero lo que realmente nos interesa es tener el conjunto que cumple la relación que hemos definido. A esto le llamamos INNER JOIN. Para eso tenemos que condicionar el ID de institución de cada uno de los autores a ser igual al ID de la institución a la que pertenecen. Esto deja fuera aquellas filas que no cumplen la relación. Hay (al menos) dos maneras de hacer esto. La primera es usar la clásula WHERE que mencionamos anteriormente:
SELECT * FROM autores, instituciones WHERE autores.institucion_id = instituciones.institucion_id;
autor_id | nombre | nacionalidad | fecha de nacimiento | institucion_id | institucion_id | nombre |
---|---|---|---|---|---|---|
1 | Edgser Dijkstra | Danés | 1930-05-11 | 2 | 2 | Universität Leiden |
2 | Niklaus Wirth | Suizo | 1934-02-15 | 1 | 1 | Xerox PARC |
Hay una cosa interesante a destacar,
y es que hemos utilizado
los nombres calificados
de las columnas,
anteponiéndoles a cada uno el nombre
de la tabla correspondiente.
Si no hiciéramos esto,
es decir,
si pusiéramos simplemente
institucion_id = institucion_id
,
PostgreSQL nos diría que
el nombre institucion_id
es ambiguo,
pues no puede determinar
a qué tabla corresponde.
Otra forma de expresar esto mismo es usando la sintaxis explícita de JOIN, en la cual ya no separamos las tablas con una coma (,) sino con la palabra clave JOIN, e indicamos la columna que debe ser igual usando USING:
SELECT * FROM autores JOIN instituciones USING (institucion_id);
institucion_id | autor | nombre | nacionalidad | fecha de nacimiento | nombre |
---|---|---|---|---|---|
2 | 1 | Edgser Dijkstra | Danés | 1930-05-11 | Eindhoven University |
1 | 2 | Niklaus Wirth | Suizo | 1934-02-15 | Xerox PARC |
Observe que ya no aparece
la columna institucion_id
dos veces,
y que las columnas
no están en el mismo orden
que antes.
Por este motivo
es importante
no confiar en el orden de las columnas;
en particular,
no es buena idea usar *
en una aplicación:
siempre es mejor listar las columnas deseadas
explícitamente.
Podemos usar ON en lugar de USING, lo que nos da más flexibilidad para escoger un criterio de combinación que USING, al precio de ser un poco más verboso:
SELECT a.nombre AS autor, i.nombre AS institucion, nacionalidad FROM autores AS a JOIN instituciones AS i ON (a.institucion_id = i.institucion_id);
Observe que,
además de hacer ese cambio,
hemos definido alias
para las tablas en la cláusula FROM,
usando la cláusula AS.
Estos alias
permiten escribir
el resto de la consulta
en una forma más breve.
También hemos definido
alias para las columnas
(de lo contrario tendríamos
dos columnas llamadas nombre
).
autor | institucion | nacionalidad |
---|---|---|
Edgser Dijkstra | Eindhoven University | Danés |
Niklaus Wirth | Xerox PARC | Suizo |
En esta sección hemos omitido hablar de OUTER JOIN, de condiciones más complejas en ON y USING, del uso de NATURAL JOIN, y el uso de más de un JOIN en una consulta, tanto implícito como explícito.