47 - Subconsultas como expresión

Una subconsulta puede reemplazar una expresión. Dicha subconsulta debe devolver un valor escalar (o una lista de valores de un campo).

Las subconsultas que retornan un solo valor escalar se utiliza con un operador de comparación o en lugar de una expresión:

 select CAMPOS
  from TABLA
  where CAMPO OPERADOR (SUBCONSULTA);

 select CAMPO OPERADOR (SUBCONSULTA)
  from TABLA;

Si queremos saber el precio de un determinado libro y la diferencia con el precio del libro más costoso, anteriormente debíamos averiguar en una consulta el precio del libro más costoso y luego, en otra consulta, calcular la diferencia con el valor del libro que solicitamos. Podemos conseguirlo en una sola sentencia combinando dos consultas:

 select titulo,precio,
  precio-(select max(precio) from libros) as diferencia
  from libros
  where titulo='Uno';

En el ejemplo anterior se muestra el título, el precio de un libro y la diferencia entre el precio del libro y el máximo valor de precio.

Queremos saber el título, autor y precio del libro más costoso:

 select titulo,autor, precio
  from libros
  where precio=(select max(precio) from libros);

Note que el campo del "where" de la consulta exterior es compatible con el valor retornado por la expresión de la subconsulta.

Se pueden emplear en "select", "insert", "update" y "delete".

Para actualizar un registro empleando subconsulta la sintaxis básica es la siguiente:

 update TABLA set CAMPO=NUEVOVALOR
  where CAMPO=(SUBCONSULTA);

Para eliminar registros empleando subconsulta empleamos la siguiente sintaxis básica:

 delete from TABLA
  where CAMPO=(SUBCONSULTA);

Recuerde que la lista de selección de una subconsulta que va luego de un operador de comparación puede incluir sólo una expresión o campo (excepto si se emplea "exists" o "in").

No olvide que las subconsultas luego de un operador de comparación (que no es seguido por "any" o "all") no pueden incluir cláusulas "group by".

Problema resuelto

Trabajamos con la tabla "libros" de una librería.
Borramos la tabla si ya existe:

drop table if exists libros;

Creamos la tabla con la siguiente estructura:

create table libros(
	codigo integer primary key,
	titulo text,
	autor text, 
	editorial text,
	precio real
);

Almacenamos una serie de filas como ejemplo:

 insert into libros(titulo,autor,editorial,precio)
  values('Uno','Richard Bach','Planeta',10.00);
 insert into libros (titulo, autor, editorial, precio)
  values('El aleph', 'Borges', 'Emece', null);
 insert into libros (titulo, autor, editorial, precio)
  values('Antología poética', 'Borges', 'Planeta', 39.50);
 insert into libros (titulo, autor, editorial, precio)
  values('Java en 10 minutos', 'Mario Molina', 'Planeta', 50.50);
 insert into libros (titulo, autor, editorial, precio)
  values('Alicia en el pais de las maravillas', 'Lewis Carroll', 'Emece', 19.90);
 insert into libros (titulo, autor, editorial, precio)
  values('Martin Fierro', 'Jose Hernandez', 'Emece', 25.90);
 insert into libros (titulo, autor, editorial, precio)
  values('Martin Fierro', 'Jose Hernandez', 'Paidos', 16.80);
 insert into libros (titulo, autor, editorial, precio)
  values('Aprenda PHP', 'Mario Molina', 'Emece', 19.50);
 insert into libros (titulo, autor, editorial, precio)
  values('Cervantes y el quijote','Borges', 'Paidos', 18.40);

Obtenemos el título, precio de un libro específico y la diferencia entre su precio y el máximo valor:

 select titulo,precio,
  precio-(select max(precio) from libros) as diferencia
  from libros
  where titulo='Uno';

Mostramos el título y precio del libro más costoso:

 select titulo,autor, precio
  from libros
  where precio=(select max(precio) from libros);  

Actualizamos el precio del libro con máximo valor:

 update libros set precio=45
  where precio=(select max(precio) from libros);  

Eliminamos los libros con precio menor:

 delete from libros
  where precio=(select min(precio) from libros);  

Problema propuesto

Un profesor almacena el documento, nombre y la nota final de cada alumno de su clase en una tabla llamada "alumnos".

  1. Borrar la tabla "alumnos" si existe.

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

    create table alumnos(
      documento text primary key,
      nombre text,
      nota real
    );
    
  3. Almacenar las siguientes filas:

     insert into alumnos(documento, nombre, nota)
      values('30111111','Ana Algarbe',5.1);
     insert into alumnos(documento, nombre, nota)
      values('30222222','Bernardo Bustamante',3.2);
     insert into alumnos(documento, nombre, nota)
      values('30333333','Carolina Conte',4.5);
     insert into alumnos(documento, nombre, nota)
      values('30444444','Diana Dominguez',9.7);
     insert into alumnos(documento, nombre, nota)
      values('30555555','Fabian Fuentes',8.5);
     insert into alumnos(documento, nombre, nota)
      values('30666666','Gaston Gonzalez',9.70);
    
  4. Obtenga todos los datos de los alumnos con la nota más alta, empleando subconsulta.

  5. Muestre los alumnos que tienen una nota menor al promedio, su nota, y la diferencia con el promedio.

  6. Elimine los alumnos cuya nota es menor al promedio.

Solución
drop table if exists alumnos;

create table alumnos(
  documento text primary key,
  nombre text,
  nota real
);

 insert into alumnos(documento, nombre, nota)
  values('30111111','Ana Algarbe',5.1);
 insert into alumnos(documento, nombre, nota)
  values('30222222','Bernardo Bustamante',3.2);
 insert into alumnos(documento, nombre, nota)
  values('30333333','Carolina Conte',4.5);
 insert into alumnos(documento, nombre, nota)
  values('30444444','Diana Dominguez',9.7);
 insert into alumnos(documento, nombre, nota)
  values('30555555','Fabian Fuentes',8.5);
 insert into alumnos(documento, nombre, nota)
  values('30666666','Gaston Gonzalez',9.70);
 
 select alumnos.*
  from alumnos
  where nota=(select max(nota) from alumnos); 
  
 select alumnos.*,
 (select avg(nota) from alumnos)-nota as diferencia
  from alumnos
  where nota<(select avg(nota) from alumnos); 
   
delete from alumnos
 where nota<(select avg(nota) from alumnos);   

Ejecución de ejercicios online

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

Resultado.....