Composición (Join)

Recordemos que se trata de un producto cartesiano restringido, las tuplas que se emparejan deben cumplir una determinada condición.

En el álgebra relacional sólo hemos hablado de composiciones en general. Sin embargo, en SQL se trabaja con varios tipos de composiciones.

Composiciones internas

Todas las composiciones que hemos visto hasta ahora se denominan composiciones internas. Para hacer una composición interna se parte de un producto cartesiano y se eliminan aquellas tuplas que no cumplen la condición de la composición.

En el ejemplo anterior tenemos 24 tuplas procedentes del producto cartesiano de las tablas personas2 y teléfonos2. Si la condición para la composición es que personas2.id=telefonos2.id, tendremos que eliminar todas las tuplas en que la condición no se cumpla.

Estas composiciones se denominan internas porque en la salida no aparece ninguna tupla que no esté presente en el producto cartesiano, es decir, la composición se hace en el interior del producto cartesiano de las tablas.

Para consultar la sintaxis de las composiciones ver JOIN.

Las composiciones internas usan estas sintaxis:

referencia_tabla, referencia_tabla
referencia_tabla [INNER | CROSS] JOIN referencia_tabla [condición]

La condición puede ser:

ON expresión_condicional | USING (lista_columnas)

La coma y JOIN son equivalentes, y las palabras INNER y CROSS son opcionales.

La condición en la cláusula ON puede ser cualquier expresión válida para una cláusula WHERE, de hecho, en la mayoría de los casos, son equivalentes.

La cláusula USING nos permite usar una lista de atributos que deben ser iguales en las dos tablas a componer.

Siguiendo con el mismo ejemplo, la condición más lógica para la composición interna entre personas2 y teléfonos2 es la igualdad entre el identificador de persona en la primera tabla y el atributo persona en la segunda:

mysql> SELECT * FROM personas2, telefonos2
    -> WHERE personas2.id=telefonos2.id;
+----+-----------+------------+-----------+----+
| id | nombre    | fecha      | numero    | id |
+----+-----------+------------+-----------+----+
|  1 | Fulanito  | 1956-12-14 | 123456789 |  1 |
|  1 | Fulanito  | 1956-12-14 | 145654854 |  1 |
|  1 | Fulanito  | 1956-12-14 | 152452545 |  1 |
|  2 | Menganito | 1975-10-15 | 254254254 |  2 |
|  4 | Fusganita | 1976-08-25 | 456545654 |  4 |
|  4 | Fusganita | 1976-08-25 | 441415414 |  4 |
+----+-----------+------------+-----------+----+
6 rows in set (0.73 sec)

mysql>

Esta consulta es equivalente a estas otras:

mysql> SELECT * FROM personas2 JOIN telefonos2 
    -> ON (personas2.id = telefonos2.id);
mysql> SELECT * FROM personas2 JOIN telefonos2 
    -> WHERE (personas2.id = telefonos2.id);
mysql> SELECT * FROM personas2 INNER JOIN telefonos2 
    -> ON (personas2.id = telefonos2.id);
mysql> SELECT * FROM personas2 CROSS JOIN telefonos2 
    -> ON (personas2.id = telefonos2.id);
mysql> SELECT * FROM personas2 JOIN telefonos2 USING(id);

En cualquier caso, la salida sólo contiene las tuplas que emparejan a personas con sus números de teléfono. Las tuplas correspondientes a personas que no tienen ningún número no aparecen, como por ejemplo las correspondientes a "Tulanita". Para las personas con varios números, se repiten los datos de la persona para cada número, por ejemplo con "Fulanito" o "Fusganita".

Composición interna natural

Consiste en una proyección sobre un producto cartesiano restringido. Es decir, sólo elegimos determinadas columnas de ambas tablas, en lugar de seleccionar todas.

Podemos hacer esto a partir de una composición general, eligiendo todas las columnas menos las repetidas:

mysql> SELECT personas2.id,nombre,fecha,numero 
    -> FROM personas2, telefonos2
    -> WHERE personas2.id=telefonos2.id;
+----+-----------+------------+-----------+
| id | nombre    | fecha      | numero    |
+----+-----------+------------+-----------+
|  1 | Fulanito  | 1956-12-14 | 123456789 |
|  1 | Fulanito  | 1956-12-14 | 145654854 |
|  1 | Fulanito  | 1956-12-14 | 152452545 |
|  2 | Menganito | 1975-10-15 | 254254254 |
|  4 | Fusganita | 1976-08-25 | 456545654 |
|  4 | Fusganita | 1976-08-25 | 441415414 |
+----+-----------+------------+-----------+
6 rows in set (0.00 sec)

mysql>

Como la columna id existe en ambas tablas estamos obligados a usar el nombre completo para esta columna. En este caso hemos optado por personas2.id, pero hubiese sido igual usar telefonos2.id.

También podemos definir alias para las tablas, y conseguir una consulta más compacta:

mysql> SELECT t1.id,nombre,fecha,numero
    -> FROM personas2 AS t1, telefonos2 AS t2
    -> WHERE t1.id=t2.id;

Por supuesto, podemos usar JOIN y ON en lugar de la coma y WHERE:

mysql> SELECT t1.id,nombre,fecha,numero
    -> FROM personas2 AS t1 JOIN telefonos2 AS t2
    -> ON t1.id=t2.id;

Pero tenemos una sintaxis alternativa mucho mejor para hacer composiciones internas naturales:

referencia_tabla NATURAL JOIN referencia_tabla

Por ejemplo:

mysql> SELECT * FROM personas2 NATURAL JOIN telefonos2;
+----+-----------+------------+-----------+
| id | nombre    | fecha      | numero    |
+----+-----------+------------+-----------+
|  1 | Fulanito  | 1956-12-14 | 123456789 |
|  1 | Fulanito  | 1956-12-14 | 145654854 |
|  1 | Fulanito  | 1956-12-14 | 152452545 |
|  2 | Menganito | 1975-10-15 | 254254254 |
|  4 | Fusganita | 1976-08-25 | 456545654 |
|  4 | Fusganita | 1976-08-25 | 441415414 |
+----+-----------+------------+-----------+
6 rows in set (0.02 sec)

mysql>

Comentarios de los usuarios (2)

Nesto David Figueroa - Colombia
2010-01-30 21:37:10

muy buena los cursos. Pero podrian realizar videotutoriales. Me parece que es una manera mas rapida de aprender. Gracias por la informacion.

Luis Alberto Vaca Diaz
2011-11-08 23:07:07

Hola de nuevo, sigo buscando el tema de referencias cruzadas, pero creo que ya estoy confundido. Necesito una consulta que me arroje resultados de la siguiente manera:

producto fecha1 fecha2 fecha3

x cantidad1 cantidad2 cantidad3

y cantidad4 cantidad5 cantidad6

y la consulta q he conseguido se muestra asi:

producto fecha cantidad

x fecha1 cantidad1

x fecha2 cantidad2

x fecha3 cantidad3

y fecha1 cantidad4

y fecha2 cantidad5

y fecha3 cantidad6

Me parece que es mucho mas presentable el primer resultado, pero no se como hacerlo, ojala y pudieran ayudarme.

Saludos y de antemano muchas gracjas