39 - Autocombinación

Podemos combinar una tabla consigo misma, esto se logra utilizando el "cross join" o "inner join". Implementaremos un ejemplo para explicar su funcionamiento.

Problema resuelto

Un pequeño restaurante tiene almacenados los nombres, precios y rubros de sus comidas en una tabla llamada "comidas".

drop table if exists comidas;

Creamos la tabla comidas con la siguiente estructura:

 create table comidas(
  codigo integer primary key,
  nombre text,
  precio real,
  rubro text  --'plato' o 'postre'
 );

Insertamos una serie de filas en la tabla "comidas":

 insert into comidas(nombre,precio,rubro) values('ravioles',5,'plato');
 insert into comidas(nombre,precio,rubro) values('tallarines',4,'plato');
 insert into comidas(nombre,precio,rubro) values('milanesa',7,'plato');
 insert into comidas(nombre,precio,rubro) values('cuarto de pollo',6,'plato');
 insert into comidas(nombre,precio,rubro) values('flan',2.5,'postre');
 insert into comidas(nombre,precio,rubro) values('porcion torta',3.5,'postre'); 

Hacemos una autocombinación utilizando "cross join":

 select c1.nombre as platoprincipal,
  c2.nombre as postre,
  c1.precio+c2.precio as total
  from comidas as c1
  cross join comidas as c2;

Note que aparecen filas duplicadas, por ejemplo, "ravioles" se combina con "ravioles" y la combinación "ravioles - flan" se repite como "flan - ravioles". Debemos especificar que combine el rubro "plato" con "postre":

 select c1.nombre as platoprincipal,
  c2.nombre as postre,
  c1.precio+c2.precio as total
  from comidas as c1
  cross join comidas as c2
  where c1.rubro='plato' and
  c2.rubro='postre';  

La salida muestra cada plato combinado con cada postre, y una columna extra que calcula el total del menú.

También se puede realizar una autocombinación con "join":

 select c1.nombre as platoprincipal,
  c2.nombre as postre,
  c1.precio+c2.precio as total
  from comidas as c1
  join comidas as c2
  on c1.codigo<>c2.codigo
  where c1.rubro='plato' and
  c2.rubro='postre';

Problema propuesto

Varios clubes de barrio se organizaron para realizar campeonatos entre ellos. La tabla llamada "equipos" guarda la información de los distintos equipos que jugarán.

  1. Borrar la tabla "equipos" si existe.

  2. Crear la tabla "equipos" con la siguiente estructura:

    create table equipos (
    	nombre text primary key,
    	barrio text,
    	domicilio text,
    	entrenador text
    );
    
  3. Almacenar algunos registros para probar luego los select:

     insert into equipos(nombre, barrio, domicilio, entrenador)
      values('Los tigres','Gral. Paz','Sarmiento 234','Juan Lopez');
     insert into equipos(nombre, barrio, domicilio, entrenador)
      values('Los leones','Centro','Colon 123','Gustavo Fuentes');
     insert into equipos(nombre, barrio, domicilio, entrenador)
      values('Campeones','Pueyrredon','Guemes 346','Carlos Moreno');
     insert into equipos(nombre, barrio, domicilio, entrenador)
      values('Cebollitas','Alberdi','Colon 1234','Luis Duarte');
    
  4. Cada equipo jugará con todos los demás 2 veces, una vez en cada sede. Realice un "cross join" para combinar los equipos teniendo en cuenta que un equipo no juega consigo mismo.

  5. Obtenga el mismo resultado empleando un "join".

  6. Realice un "cross join" para combinar los equipos para que cada equipo juegue con cada uno de los otros una sola vez.

Solución
drop table if exists equipos;

create table equipos (
	nombre text primary key,
	barrio text,
	domicilio text,
	entrenador text
);

 insert into equipos(nombre, barrio, domicilio, entrenador)
  values('Los tigres','Gral. Paz','Sarmiento 234','Juan Lopez');
 insert into equipos(nombre, barrio, domicilio, entrenador)
  values('Los leones','Centro','Colon 123','Gustavo Fuentes');
 insert into equipos(nombre, barrio, domicilio, entrenador)
  values('Campeones','Pueyrredon','Guemes 346','Carlos Moreno');
 insert into equipos(nombre, barrio, domicilio, entrenador)
  values('Cebollitas','Alberdi','Colon 1234','Luis Duarte');
  
 select e1.nombre,e2.nombre,e1.barrio as sede
  from equipos as e1
  cross join equipos as e2
  where e1.nombre<>e2.nombre;  
  
select e1.nombre,e2.nombre,e1.barrio as sede
  from equipos as e1
  join equipos as e2
  on e1.nombre<>e2.nombre;

select e1.nombre,e2.nombre,e1.barrio as sede
  from equipos as e1
  cross join equipos as e2
  where e1.nombre>e2.nombre;

Ejecución de ejercicios online

Puede ejecutar comandos de SQLite directamente en el sitio sin tener que instalar nada en su computadora.

Resultado.....