2.5.6. Consultas de mas de una tabla
2.5.6. Consultas de mas de una tabla Dataprix 21 September, 2009 - 11:17Muchas veces queremos consultar datos de más de una tabla haciendo combinaciones de columnas de tablas diferentes. En el SQL es posible listar más de una tabla que se quiere consultar especificándolo en la cláusula FROM.
1) Combinación
Recordad que la misma operación de combinación, pero del álgebra relacional, se ha visto en el subapartado 5.3.3. de la unidad "El modelo relacional y el álgebra relacional" |
La combinación consigue crear una sola tabla a partir de las tablas especificadas en la cláusula FROM, haciendo coincidir los valores de las columnas relacionadas de estas tablas.
Ejemplo de combinación en BDUOC
A continuación mostramos un ejemplo con la base de datos BDUOC en el que queremos saber el NIF del cliente y el código y el precio del proyecto que desarrollamos para el cliente número 20:
SELECT proyectos.codigo_proyecto, proyectos.precio, clientes.nif
FROM clientes, proyectos
WHERE clientes.codigo_cli = proyectos.codigo_cliente AND clientes.
codigo_cli = 20;
El resultado sería:
proyectos.codigo_proyecto | proyectos.precio | clientes.nif |
---|---|---|
3 | 1.000.000 | 38.123.898-E |
Si trabajamos con más de una tabla, puede ocurrir que la tabla resultante tenga dos columnas con el mismo nombre. Por ello es obligatorio especificar a qué tabla corresponden las columnas a las que nos estamos refiriendo, denominando la tabla a la que pertenecen antes de ponerlas (por ejemplo, clientes.codigo_cli). Para simplificarlo, se utilizan los alias que, en este caso, se definen en la cláusula FROM.
Ejemplo de alias en BDUOC
c podría ser el alias de la tabla clientes. De este modo, para indicar a qué tabla pertenece codigo_cli, sólo haría falta poner: c.codigo_cli.
Veamos cómo quedaría la consulta anterior expresada mediante alias, aunque en este ejemplo no serían necesarios, porque todas las columnas de las dos tablas tienen nombres diferentes. Pediremos, además, las columnas c.codigo_cli y p.codigo_cliente.
SELECT p.codigo_proyecto, p.precio, c.nif, p.codigo_cliente, c.codigo_cli
FROM clientes c, proyectos p
WHERE c.codigo_cli = p.codigo_cliente AND c.codigo_cli = 20;
Entonces obtendríamos este resultado:
p.codigo_proyec | p.precio | c.nif | p.codigo_cliente | c.codigo_cli |
---|---|---|---|---|
3 | 1.000.000 | 38.123.898-E | 20 | 20 |
Notemos que en WHERE necesitamos expresar el vínculo que se establece entre las dos tablas, en este caso codigo_cli de clientes y codigo_cliente de proyectos. Expresado en operaciones del álgebra relacional, esto significa que hacemos una combinación en lugar de un producto cartesiano.
Las operaciones del álgebra relacional se han visto en el apartado 5 de la unidad "El modelo relacional y el álgebra relacional" |
Fijémonos en que, al igual que en álgebra relacional, la operación que acabamos de hacer es una equicombinación (equi-join); por lo tanto, nos aparecen dos columnas idénticas: c.codigo_cli y p.codigo_cliente.
La forma de expresar la combinación que acabamos de ver pertenece al SQL92 introductorio. Una forma alternativa de realizar la equicombinación anterior, utilizando el SQL92 intermedio o completo, sería la siguiente:
SELECT nombre_columnas_a_seleccionar
FROM tabla1 JOIN tabla2
{ON condiciones|USING (columna [, columna...])}
[WHERE condiciones];
Ejemplo anterior con el SQL92 intermedio o completo
El ejemplo que hemos expuesto antes utilizando el SQL92 intermedio o completo sería:
SELECT p.codigo_proyecto, p.precio, c.nif, p.codigo_cliente, c.codigo_cli
FROM clientes c JOIN proyectos p ON c.codigo_cli = p.codigo_cliente
WHERE c.codigo_cli = 20;
Y obtendríamos el mismo resultado de antes.
Pdemos ver la equicombinación y la Ø-combinación en el subapartado 5.3.3. de la unidad "El modelo relacional y el álgebra relacional" |
La opción ON, además de expresar condiciones con la igualdad, en el caso de que las columnas que queramos vincular tengan nombres diferentes, nos ofrece la posibilidad de expresar condiciones con los demás operadores de comparación que no sean el de igualdad. Sería el equivalente a la operación que en álgebra relacional hemos denominado Ø-combinación (Ø-join).
También podemos utilizar una misma tabla dos veces con alias diferentes, para distinguirlas.
Dos alias para una misma tabla en BDUOC
Si pidiésemos los códigos y los apellidos de los empleados que ganan más que el empleado que tiene por código el número 5, haríamos lo siguiente:
SELECT p.codigo_proyecto, p.precio, c.nif, p.codigo_cliente, c.codigo_cli
FROM clientes c JOIN proyectos p ON c.codigo_cli = p.codigo_cliente
WHERE c.codigo_cli = 20;
Hemos tomado la tabla e2 para fijar la fila del empleado con código número 5, de modo que
podamos comparar el sueldo de la tabla e1, que contiene a todos los empleados, con el sueldo de la tabla e2, que contiene sólo al empleado 5.
La respuesta a esta consulta sería:
e1.codigo_empl | e1.apellido_empl |
---|---|
1 | Puig |
2 | Mas |
3 | Ros |
4 | Roca |
2) Combinación natural
La combinación natural (natural join) de dos tablas consiste básicamente, al igual que en el álgebra relacional, en hacer una equicombinación entre columnas del mismo nombre y eliminar las columnas repetidas. La combinación natural, utilizando el SQL92 intermedio o completo, se haría de la forma siguiente:
SELECT nombre_columnas_a_seleccionar
FROM tabla1 NATURAL JOIN tabla2
[WHERE condiciones];
Combinación natural en BDUOC
Veamos a continuación un ejemplo en el que las columnas para las que se haría la combinación natural se denominan igual en las dos tablas. Ahora queremos saber el código y el nombre de los empleados que están asignados al departamento cuyo teléfono es 977.33.38.52:
SELECT codigo_empl, nombre_empl
FROM empleados NATURAL JOIN departamentos
WHERE telefono = '977.333.852';
La combinación natural también se podría hacer con la cláusula USING, sólo aplicando la palabra reservada JOIN:
SELECT codigo_empl, nombre_empl
FROM empleados JOIN departamentos USING (nombre_dep, ciudad_dep)
WHERE telefono = '977.333.852';
La respuesta que daría sería:
empleados.codigo_empl | empleados.nombre_empl |
---|---|
5 | Clara |
6 | Laura |
8 | Sergio |
3) Combinación interna y externa
Cualquier combinación puede ser interna o externa:
a) La combinación interna (inner join) sólo se queda con las filas que tienen valores idénticos en las columnas de las tablas que compara. Esto puede hacer que perdamos alguna fila interesante de alguna de las dos tablas; por ejemplo, porque se encuentra a NULL en el momento de hacer la combinación. Su formato es el siguiente:
SELECT nombre_columnas_a_seleccionar
FROM t1 [NATURAL] [INNER] JOIN t2
{ON condiciones|
|USING(columna [,columna...])}
[WHERE condiciones];
b) Por ello disponemos de la combinación externa (outer join), que nos permite obtener todos los valores de la tabla que hemos puesto a la derecha, los de la tabla que hemos puesto a la izquierda o todos los valores de las dos tablas. Su formato es:
SELECT nombre_columnas_a_seleccionar
FROM t1 [NATURAL] [LEFT|RIGHT|FULL] [OUTER] JOIN t2
{ON condiciones|
[USING (columna [,columna...])}
[WHERE condiciones];
Combinación natural interna en BDUOC
Combinación interna |
Aunque en el ejemplo estamos haciendo una combinación natural interna, no es necesario poner la palabra INNER, ya que es la opción por defecto. |
Si quisiéramos vincular con una combinación natural interna las tablas empleados y
departamentos para saber el código y el nombre de todos los empleados y el nombre, la ciudad y el teléfono de todos los departamentos, haríamos:
SELECT e.codigo_empl, e.nombre_empl, e.nombre_dep, e.ciudad_dep, d.telefono
FROM empleados e NATURAL JOIN departamentos d;
Y obtendríamos el siguiente resultado:
e.codigo_empl | e.nombre_empl | e.nombre_dep | e.ciudad_dep | d.teléfono |
---|---|---|---|---|
1 | María | DIR | Girona | 972.23.89.70 |
2 | Pedro | DIR | Barcelona | 93.422.60.70 |
3 | Ana | DIS | Lleida | 973.23.50.40 |
4 | Jorge | DIS | Barcelona | 93.224.85.23 |
5 | Clara | PROG | Tarragona | 977.33.38.52 |
6 | Laura | PROG | Tarragona | 977.33.38.52 |
8 | Sergio | PROG | Tarragona | 977.33.38.52 |
Fijémonos en que en el resultado no aparece el empleado número 7, que no está asignado a ningún departamento, ni el departamento de programación de Girona, que no tiene ningún empleado asignado.
Combinación natural externa a BDUOC
En los ejemplos siguientes veremos cómo varían los resultados que iremos obteniendo según los tipos de combinación externa:
a) Combinación externa izquierda
SELECT e.codigo_empl, e.nombre_empl, e.nombre_dep, e.ciudad_dep, d.telefono
FROM empleados e NATURAL LEFT OUTER JOIN departamentos d;
Combinación externa izquierda |
Aquí fighura el empleado 7. |
El resultado sería el que podemos ver a continuación:
e.codigo_empl | e.nombre_emple | e.nombre_dep | e.ciudad_dep | d.telefono |
---|---|---|---|---|
1 | María | DIR | Girona | 972.23.89.70 |
2 | Pedro | DIR | Barcelona | 93.422.60.70 |
3 | Ana | DIS | Lleida | 973.23.50.40 |
4 | Jorge | DIS | Barcelona | 93.224.85.23 |
5 | Clara | PROG | Tarragona | 977.33.38.52 |
6 | Laura | PROG | Tarragona | 977.33.38.52 |
7 | Rogelio | NULL | NULL | NULL |
8 | Sergio | PROG | Tarragona | 977.33.38.52 |
b) Combinación externa derecha
SELECT e.codigo_empl, e.nombre_empl, e.nombre_dep, e.ciudad_dep, d.telefono
FROM empleados e NATURAL RIGHT OUTER JOIN departamentos d;
Combinación externa derecha |
Aquí figura el departamento de programación d |
Obtendríamos este resultado:
e.codigo_empl | e.nombre_emple | e.nombre_dep | e.ciudad_dep | d.telefono |
---|---|---|---|---|
1 | María | DIR | Girona | 972.23.89.70 |
2 | Pedro | DIR | Barcelona | 93.422.60.70 |
3 | Ana | DIS | Lleida | 973.23.50.40 |
4 | Jorge | DIS | Barcelona | 93.224.85.23 |
5 | Clara | PROG | Tarragona | 977.33.38.52 |
6 | Laura | PROG | Tarragona | 977.33.38.52 |
8 | Sergio | PROG | Tarragona | 977.33.38.52 |
NULL | NULL | PROG | Girona | 9272.23.50.91 |
c) Combinación externa plena
SELECT e.codigo_empl, e.nombre_empl, e.nombre_dep, e.ciudad_dep, d.telefono
FROM empleados e NATURAL FULL OUTER JOIN departamentos d;
Combinación externa plena |
Aquí figura el empleado 7 y el departamento de programación de Girona. |
Y obtendríamos el siguiente resultado:
e.codigo_empl | e.nombre_emple | e.nombre_dep | e.ciudad_dep | d.telefono |
---|---|---|---|---|
4 | Jorge | DIS | Barcelona | 93.224.85.23 |
5 | Clara | PROG | Tarragona | 977.33.38.52 |
6 | Laura | PROG | Tarragona | 977.33.38.52 |
7 | Rogelio | NULL | NULL | NULL |
8 | Sergio | PROG | Tarragona | 977.33.38.52 |
NULL | NULL | PROG | Girona | 9272.23.50.91 |
4) Combinaciones con más de dos tablas
Si queremos combinar tres tablas o más con el SQL92 introductorio, sólo tenemos que añadir todas las tablas en el FROM y los vínculos necesarios en el WHERE. Si queremos combinarlas con el SQL92 intermedio o con el completo, tenemos que ir haciendo combinaciones de tablas por pares, y la tabla resultante se convertirá en el primer componente del siguiente par.
Combinaciones con más de dos tablas en BDUOC
Veamos ejemplos de los dos casos, suponiendo que queremos combinar las tablas empleados, proyectos y clientes:
SELECT *
FROM empleados, proyectos, clientes
WHERE num_proyec = codigo_proyec AND codigo_cliente = codigo_cli;
o bien:
SELECT *
FROM (empleados JOIN proyectos ON num_proyec = codigo_proyec)
JOIN clientes ON codigo_cliente = codigo_cli;