52 - Subconsulta en lugar de una tabla

Se pueden emplear subconsultas que retornen un conjunto de registros de varios campos en lugar de una tabla.

Se la denomina tabla derivada y se coloca en la cláusula "from" para que la use un "select" externo.

La tabla derivada debe ir entre paréntesis y tener un alias para poder referenciarla. La sintaxis básica es la siguiente:

 select ALIASdeTABLADERIVADA.CAMPO
 from (TABLADERIVADA) as ALIAS;

La tabla derivada es una subsonsulta.

Problema resuelto

Un comercio que vende artículos de librería y papelería almacena la información de sus ventas en una tabla llamada "facturas", otra "detalles" y otra "clientes".

Eliminamos las tablas si ya existen:

 drop table if exists clientes;
 drop table if exists facturas;
 drop table if exists detalles; 

Creamos las tablas con las siguientes estructuras:

 create table clientes(
  codigo integer primary key,
  nombre text,
  domicilio text
 );

 create table facturas(
  numero integer primary key,
  codigocliente integer
 );

 create table detalles(
  numerofactura integer,
  numeroitem integer, 
  articulo text,
  precio real,
  cantidad integer,
  primary key(numerofactura,numeroitem)
 );

Almacenamos algunos datos de prueba:

 insert into clientes(nombre,domicilio) values('Juan Lopez','Colon 123');
 insert into clientes(nombre,domicilio) values('Luis Torres','Sucre 987');
 insert into clientes(nombre,domicilio) values('Ana Garcia','Sarmiento 576');

 insert into facturas values(1200,1);
 insert into facturas values(1201,2);
 insert into facturas values(1202,3);
 insert into facturas values(1300,1);

 insert into detalles values(1200,1,'lapiz',1,100);
 insert into detalles values(1200,2,'goma',0.5,150);
 insert into detalles values(1201,1,'regla',1.5,80);
 insert into detalles values(1201,2,'goma',0.5,200);
 insert into detalles values(1201,3,'cuaderno',4,90);
 insert into detalles values(1202,1,'lapiz',1,200);
 insert into detalles values(1202,2,'escuadra',2,100);
 insert into detalles values(1300,1,'lapiz',1,300);

Vamos a realizar un "select" para recuperar el número de factura, el código de cliente y la suma total de todas las facturas:

 select f.*,
  (select sum(d.precio*cantidad)
    from detalles as d
    where f.numero=d.numerofactura) as total
 from facturas as f;

Esta consulta contiene una subconsulta correlacionada.

Ahora utilizaremos el resultado de la consulta anterior como una tabla derivada que emplearemos en lugar de una tabla para realizar un "join" y recuperar el número de factura, el nombre del cliente y el monto total por factura:

 select td.numero,c.nombre,td.total
  from clientes as c
  join (select f.*,
   (select sum(d.precio*cantidad)
    from detalles as d
    where f.numero=d.numerofactura) as total
  from facturas as f) as td
  on td.codigocliente=c.codigo;

Note que para referenciar la tabla derivada debimos colocar un alias a la consulta.

Problema propuesto

Un club dicta clases de distintos deportes. En una tabla llamada "socios" guarda los datos de los socios, en una tabla llamada "deportes" la información referente a los diferentes deportes que se dictan y en una tabla denominada "inscriptos", las inscripciones de los socios a los distintos deportes.
Un socio puede inscribirse en varios deportes el mismo año. Un socio no puede inscribirse en el mismo deporte el mismo año. Distintos socios se inscriben en un mismo deporte en el mismo año.

  1. Borrar las tablas si ya existen.

  2. Crear las tablas con las siguientes estructuras:

     create table socios(
      documento text primary key, 
      nombre text,
      domicilio text
     );
    
     create table deportes(
      codigo integer primary key,
      nombre text,
      profesor text
     );
     
     create table inscriptos(
      documento text, 
      codigodeporte text,
      año integer,
      matricula text,--'s'=paga, 'n'=impaga
      primary key(documento,codigodeporte,año)
     );
     
  3. Almacenamos una serie de filas en las tablas:

     insert into socios values('22222222','Ana Acosta','Avellaneda 111');
     insert into socios values('23333333','Betina Bustos','Bulnes 222');
     insert into socios values('24444444','Carlos Castro','Caseros 333');
     insert into socios values('25555555','Daniel Duarte','Dinamarca 44');
    
     insert into deportes(nombre,profesor) values('basquet','Juan Juarez');
     insert into deportes(nombre,profesor) values('futbol','Pedro Perez');
     insert into deportes(nombre,profesor) values('natacion','Marina Morales');
     insert into deportes(nombre,profesor) values('tenis','Marina Morales');
    
     insert into inscriptos values ('22222222',3,'2016','s');
     insert into inscriptos values ('23333333',3,'2016','s');
     insert into inscriptos values ('24444444',3,'2016','n');
     insert into inscriptos values ('22222222',3,'2015','s');
     insert into inscriptos values ('22222222',3,'2017','n');
     insert into inscriptos values ('24444444',1,'2016','s');
     insert into inscriptos values ('24444444',2,'2016','s');
    
  4. Realice una consulta en la cual muestre todos los datos de las inscripciones, incluyendo el nombre del deporte y del profesor.
    Esta consulta es un join.

  5. Utilice el resultado de la consulta anterior como una tabla derivada para emplear en lugar de una tabla para realizar un "join" y recuperar el nombre del socio, el deporte en el cual está inscripto, el año, el nombre del profesor y la matrícula.

Solución
 drop table if exists socios;
 drop table if exists deportes;
 drop table if exists inscriptos; 
 
 create table socios(
  documento text primary key, 
  nombre text,
  domicilio text
 );

 create table deportes(
  codigo integer primary key,
  nombre text,
  profesor text
 );
 
 create table inscriptos(
  documento text, 
  codigodeporte text,
  año integer,
  matricula text,--'s'=paga, 'n'=impaga
  primary key(documento,codigodeporte,año)
 );
 

 insert into socios values('22222222','Ana Acosta','Avellaneda 111');
 insert into socios values('23333333','Betina Bustos','Bulnes 222');
 insert into socios values('24444444','Carlos Castro','Caseros 333');
 insert into socios values('25555555','Daniel Duarte','Dinamarca 44');

 insert into deportes(nombre,profesor) values('basquet','Juan Juarez');
 insert into deportes(nombre,profesor) values('futbol','Pedro Perez');
 insert into deportes(nombre,profesor) values('natacion','Marina Morales');
 insert into deportes(nombre,profesor) values('tenis','Marina Morales');

 insert into inscriptos values ('22222222',3,'2016','s');
 insert into inscriptos values ('23333333',3,'2016','s');
 insert into inscriptos values ('24444444',3,'2016','n');
 insert into inscriptos values ('22222222',3,'2015','s');
 insert into inscriptos values ('22222222',3,'2017','n');
 insert into inscriptos values ('24444444',1,'2016','s');
 insert into inscriptos values ('24444444',2,'2016','s');
 

 select i.documento,i.codigodeporte,d.nombre as deporte, año, matricula, d.profesor
 from deportes as d
 join inscriptos as i
 on d.codigo=i.codigodeporte; 
 
 
 select s.nombre,td.deporte,td.profesor,td.año,td.matricula
  from socios as s
  join (select i.documento,i.codigodeporte,d.nombre as deporte, año, matricula, d.profesor
	from deportes as d
	join inscriptos as i
	on d.codigo=i.codigodeporte) as td
  on td.documento=s.documento; 

Ejecución de ejercicios online

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

Resultado.....