Composiciones externas

Al contrario que con las composiciones internas, las externas no proceden de un producto cartesiano. Por lo tanto, en estas pueden aparecer tuplas que no aparecen en el producto cartesiano.

Para hacer una composición externa se toman las tuplas de una de las tablas una a una y se combinan con las tuplas de la otra.

Como norma general se usa un índice para localizar las tuplas de la segunda tabla que cumplen la condición, y para cada tupla encontrada se añade una fila a la tabla de salida.

Si no existe ninguna tupla en la segunda tabla que cumpla las condiciones, se combina la tupla de la primera con una nula de la segunda.

En nuestro ejemplo se tomaría la primera tupla de personas2, con un valor de id igual a 1, y se busca en la tabla telefonos2 las tuplas con un valor de id igual a 1. Lo mismo para la segunda tupla, con id igual a 2.

En la tercera el id es 3, y no existe ninguna tupla en telefonos2 con un valor de id igual a 3, por lo tanto se combina la tupla de personas2 con una tupla de telefonos2 con todos los atributos igual a NULL.

Por ejemplo:

mysql> SELECT * FROM personas2 LEFT JOIN telefonos2 USING(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 |
|  3 | Tulanita  | 1985-03-17 | NULL      | NULL | (1)
|  4 | Fusganita | 1976-08-25 | 456545654 |    4 |
|  4 | Fusganita | 1976-08-25 | 441415414 |    4 |
+----+-----------+------------+-----------+------+
7 rows in set (0.05 sec)

mysql>

La quinta fila (1), tiene valores NULL para numero e id de telefonos2, ya que no existen tuplas en esa tabla con un valor de id igual a 3.

Las sintaxis para composiciones externas son:

referencia_tabla LEFT [OUTER] JOIN referencia_tabla [join_condition]
referencia_tabla NATURAL LEFT [OUTER] JOIN referencia_tabla
referencia_tabla RIGHT [OUTER] JOIN referencia_tabla [condición]
referencia_tabla NATURAL RIGHT [OUTER] JOIN referencia_tabla

La condición puede ser:

ON expresión_condicional | USING (lista_columnas)

La palabra OUTER es opcional.

Existen dos grupos de composiciones externas: izquierda y derecha, dependiendo de cual de las tablas se lea en primer lugar.

Composición externa izquierda

En estas composiciones se recorre la tabla de la izquierda y se buscan tuplas en la de la derecha. Se crean usando la palabra LEFT (izquierda, en inglés).

Las sintaxis para la composición externa izquierda es:

referencia_tabla LEFT [OUTER] JOIN referencia_tabla [condición]

Veamos un ejemplo. Para empezar, crearemos un par de tablas:

mysql> CREATE TABLE tabla1 (
    -> id INT NOT NULL,
    -> nombre CHAR(10),
    -> PRIMARY KEY (id));
Query OK, 0 rows affected (0.42 sec)

mysql> CREATE TABLE tabla2 (
    -> id INT NOT NULL,
    -> numero INT,
    -> PRIMARY KEY (id));
Query OK, 0 rows affected (0.11 sec)

mysql>

E insertaremos algunos datos:

mysql> INSERT INTO tabla1 VALUES
    -> (5, "Juan"),
    -> (6, "Pedro"),
    -> (7, "José"),
    -> (8, "Fernando");
Query OK, 4 rows affected (0.06 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> INSERT INTO tabla2 VALUES
    -> (3, 30),
    -> (4, 40),
    -> (5, 50),
    -> (6, 60);
Query OK, 5 rows affected (0.05 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql>

La composición izquierda sería:

mysql> SELECT * FROM tabla1 LEFT JOIN tabla2 USING(id);
+----+----------+------+--------+
| id | nombre   | id   | numero |
+----+----------+------+--------+
|  5 | Juan     |    5 |     50 |
|  6 | Pedro    |    6 |     60 |
|  7 | José     | NULL |   NULL |
|  8 | Fernando | NULL |   NULL |
+----+----------+------+--------+
4 rows in set (0.00 sec)

mysql>

Se puede ver que aparecen dos filas con valores NULL, para los id 7 y 8.

En contraposición, una composición interna dará esta salida:

mysql> SELECT * FROM tabla1 JOIN tabla2 USING(id);
+----+--------+----+--------+
| id | nombre | id | numero |
+----+--------+----+--------+
|  5 | Juan   |  5 |     50 |
|  6 | Pedro  |  6 |     60 |
+----+--------+----+--------+
2 rows in set (0.06 sec)

mysql>

Composición externa derecha

En este caso se recorre la tabla de la derecha y se buscan tuplas que cumplan la condición en la tabla izquierda.

La sintaxis es equivalente:

referencia_tabla LEFT [OUTER] JOIN referencia_tabla [condición]

Usando las mismas tablas que en el ejemplo anterior:

mysql> SELECT * FROM tabla1 RIGHT JOIN tabla2 USING(id);
+------+--------+----+--------+
| id   | nombre | id | numero |
+------+--------+----+--------+
| NULL | NULL   |  3 |     30 |
| NULL | NULL   |  4 |     40 |
|    5 | Juan   |  5 |     50 |
|    6 | Pedro  |  6 |     60 |
+------+--------+----+--------+
4 rows in set (0.00 sec)

mysql>

Es lo mismo usar una composición derecha de las tablas tabla1 y tabla2 que una composición izquierda de las tablas tabla2 y tabla1. Es decir, la consulta anterior es equivalente a esta otra:

mysql> SELECT * FROM tabla2 LEFT JOIN tabla1 USING(id);

Composiciones naturales externas

Por supuesto, también podemos hacer composiciones externas naturales:

referencia_tabla NATURAL LEFT [OUTER] JOIN referencia_tabla
referencia_tabla NATURAL RIGHT [OUTER] JOIN referencia_tabla

El problema es que si existen tuplas añadidas con respecto a la composición interna, no se eliminará ninguna columna. Los mismos ejemplos anteriores, como composiciones naturales externas serían:

mysql> SELECT * FROM tabla1 NATURAL LEFT JOIN tabla2;
+----+----------+------+--------+
| id | nombre   | id   | numero |
+----+----------+------+--------+
|  5 | Juan     |    5 |     50 |
|  6 | Pedro    |    6 |     60 |
|  7 | José     | NULL |   NULL |
|  8 | Fernando | NULL |   NULL |
+----+----------+------+--------+
4 rows in set (0.00 sec)

mysql> SELECT * FROM tabla1 NATURAL RIGHT JOIN tabla2;
+------+--------+----+--------+
| id   | nombre | id | numero |
+------+--------+----+--------+
| NULL | NULL   |  3 |     30 |
| NULL | NULL   |  4 |     40 |
|    5 | Juan   |  5 |     50 |
|    6 | Pedro  |  6 |     60 |
+------+--------+----+--------+
4 rows in set (0.00 sec)

mysql>