Listado completo de tutoriales
64 - Varias tablas (left join) |
Hemos visto cómo usar registros de una tabla para encontrar registros de otra tabla, uniendo ambas tablas con "join" y enlazándolas con una condición "on" en la cual colocamos el campo en común. O sea, hacemos un "join" y asociamos registros de 2 tablas usando el "on", buscando coincidencia en los valores del campo que tienen en comun ambas tablas.
Trabajamos con las tablas de una librería:
-libros: codigo (clave primaria), titulo, autor, codigoeditorial, precio, cantidad y -editoriales: codigo (clave primaria), nombre.
Queremos saber de qué editoriales no tenemos libros.
Para averiguar qué registros de una tabla no se encuentran en otra tabla necesitamos usar un "join" diferente.
Necesitamos determinar qué registros no tienen correspondencia en otra tabla, cuáles valores de la primera tabla (de la izquierda) no están en la segunda (de la derecha).
Para obtener la lista de editoriales y sus libros, incluso de aquellas editoriales de las cuales no tenemos libros usamos:
select * from editoriales left join libros on editoriales.codigo=libros.codigoeditorial;
Un "left join" se usa para hacer coincidir registros en una tabla (izquierda) con otra tabla (derecha), pero, si un valor de la tabla de la izquierda no encuentra coincidencia en la tabla de la derecha, se genera una fila extra (una por cada valor no encontrado) con todos los campos seteados a "null".
Entonces, la sintaxis es la siguiente: se nombran ambas tablas, una a la izquierda del "join" y la otra a la derecha, y la condición para enlazarlas, es decir, el campo por el cual se combinarán, se establece luego de "on". Es importante la posición en que se colocan las tablas en un "left join", la tabla de la izquierda es la que se usa para localizar registros en la tabla de la derecha. Por lo tanto, estos "join" no son iguales:
select * from editoriales left join libros on editoriales.codigo=libros.codigoeditorial; select * from libros left join editoriales on editoriales.codigo=libros.codigoeditorial;
La primera sentencia opera así: por cada valor de codigo de "editoriales" busca coincidencia en la tabla "libros", si no encuentra coincidencia para algún valor, genera una fila seteada a "null".
La segunda sentencia opera de modo inverso: por cada valor de "codigoeditorial" de "libros" busca coincidencia en la tabla "editoriales", si no encuentra coincidencia, setea la fila a "null".
Usando registros de la tabla de la izquierda se encuentran registros en la tabla de la derecha.
Luego del "on" se especifican los campos que se asociarán; no se deben colocar condiciones en la parte "on" para restringir registros que deberían estar en el resultado, para ello hay que usar la cláusula "where".
Un "left join" puede tener clausula "where" que restringa el resultado de la consulta considerando solamente los registros que encuentran coincidencia en la tabla de la derecha:
select e.nombre,l.titulo from editoriales as e left join libros as l on e.codigo=l.codigoeditorial where l.codigoeditorial is not null;
El anterior "left join" muestra los valores de la tabla "editoriales" que están presentes en la tabla de la derecha ("libros").
También podemos mostrar las editoriales que no están presentes en "libros":
select e.nombre,l.titulo from editoriales as e left join libros as l on e.codigo=l.codigoeditorial where l.codigoeditorial is null;
El anterior "left join" muestra los valores de la tabla "editoriales" que no encuentran correspondencia en la tabla de la derecha, "libros".
Ingresemos al programa "Workbench" y ejecutemos el siguiente bloque de instrucciones SQL:
drop table if exists libros, editoriales; create table libros( codigo int unsigned auto_increment, titulo varchar(40) not null, autor varchar(30) not null default 'Desconocido', codigoeditorial tinyint unsigned not null, precio decimal(5,2) unsigned, cantidad tinyint unsigned default 0, primary key (codigo) ); create table editoriales( codigo tinyint unsigned auto_increment, nombre varchar(20) not null, primary key(codigo) ); insert into editoriales (nombre) values('Paidos'); insert into editoriales (nombre) values('Emece'); insert into editoriales (nombre) values('Planeta'); insert into editoriales (nombre) values('Sudamericana'); insert into libros (titulo, autor,codigoeditorial,precio,cantidad) values('El Aleph','Borges',3,43.5,200); insert into libros (titulo, autor,codigoeditorial,precio,cantidad) values('Alicia en el pais de las maravillas','Lewis Carroll',2,33.5,100); insert into libros (titulo, autor,codigoeditorial,precio,cantidad) values('Aprenda PHP','Mario Perez',1,55.8,50); insert into libros (titulo, autor,codigoeditorial,precio,cantidad) values('Java en 10 minutos','Juan Lopez',1,88,150); insert into libros (titulo, autor,codigoeditorial,precio,cantidad) values('Alicia a traves del espejo','Lewis Carroll',1,15.5,80); insert into libros (titulo, autor,codigoeditorial,precio,cantidad) values('Cervantes y el quijote','Borges- Bioy Casares',3,25.5,250); insert into libros (titulo, autor,codigoeditorial,precio,cantidad) values('Aprenda Java en 10 minutos','Lopez Juan',5,28,100); -- Para obtener la lista de todas las editoriales y los libros de las mismas, -- incluso de las cuales no tenemos libros usamos: select * from editoriales left join libros on editoriales.codigo=libros.codigoeditorial; -- Los dos siguientes join no son lo mismo: select * from editoriales left join libros on editoriales.codigo=libros.codigoeditorial; select * from libros left join editoriales on editoriales.codigo=libros.codigoeditorial; -- Para encontrar los valores de código de la tabla "editoriales" -- que están presentes en la tabla "libros" usamos un "where": select nombre,titulo from editoriales as e left join libros as l on e.codigo=l.codigoeditorial where l.codigoeditorial is not null; -- Para mostrar las editoriales que no están presentes en "libros": select e.nombre,l.titulo from editoriales as e left join libros as l on e.codigo=l.codigoeditorial where l.codigoeditorial is null;
Genera una salida similar a esta: