Más consultas

Rangos

Expresiones del tipo 10 <= x <= 100 se pueden construir utilizando el operador de construcción de rangos BETWEEN. La sintaxis de tal subexpresión de la cláusula where es la siguiente:

expresión [NOT] BETWEEN expresión AND expresión

Créditos y descripción de las asignaturas cuyo número de créditos está entre 5 y 8.

select creditos, descripcion

from asignaturas

where creditos between 5 and 8

Y es equivalente a

select creditos, descripcion

from asignaturas

where creditos >= 5 and creditos <= 8

La condición contraria, que el valor comparado no esté dentro del rango, exige el modificador NOT.

select creditos, descripcion

from asignaturas

where creditos NOT between 5 and 8

Subcadenas de caracteres

Podemos preguntar por subcadenas dentro de columnas de tipo carácter. Para ello utilizaremos los operadores LIKE (o MATCHES), que soportan la siguiente sintaxis:

expresión [NOT] LIKE 'cadena'

La cadena de caracteres cadena admite los comodines % (tanto por ciento) y _ (subrayado):

  • % indica una cadena de caracteres de cualquier longitud ('Ali%' = 'Alicante', 'Aligerar', 'Ali', ...)

  • _ un carácter cualquiera ('Ali_' = 'Alic', 'Alig', 'Ali', ...)

  • combinados ('_l%' = 'Alicante', 'Albacete', 'llamada',...)

Profesores que atiendan al nombre de 'RAFA'.

select * from profesores where nombre like 'RAFA%'

Código de las asignaturas de 'Bases de Datos'

select codigo from asignaturas where descripcion like '%BASES DE DATOS%'

Código de las asignaturas, siendo tal código de 2 caracteres

select codigo from asignaturas where codigo like '__'

Descripción de las asignaturas cuya última palabra contiene 'INFORMATIC' y un caracter adicional.

select descripcion from asignaturas where descripcion like '%INFORMATIC_'

No utilices LIKE cuando quieras decir "igualdad":

select codigo from asignaturas where codigo like 'FP'

Es cierto que MariaDB no se va a "quejar" y ejecutará consecuentemente, pero deja LIKE para las comparaciones con subcadenas y utiliza el simple igual (=) cuando busques coincidencia exacta:

select codigo from asignaturas where codigo = 'FP'

Si se buscan varias subcadenas distintas que no puedan combinarse en una única expresión, lo correcto es proponer dos comparaciones LIKE:

select descripcion from asignaturas

where descripcion like '%INFORMATIC_'

OR descripcion like '%MULTI%'

La condición contraria, que no se ajuste a la cadena de formato especificada, exige el uso del modificador NOT:

select descripcion from asignaturas

where descripcion NOT like '%INFORMATIC_'

Listas

Mediante el operador IN se puede buscar un determinado valor en una lista construida usando constantes.

expresión [NOT] IN (listaValores)

Descripción de las asignaturas FBD y DGBD.

select descripcion

from asignaturas

where codigo in ('FBD', 'DGBD')

Nombre de los profesores que no imparten HI, FBD o DGBD.

select nombre

from profesores p, imparte i

where p.dni = i.dni

and asignatura not in ('HI', 'FBD', 'DGBD')

Fijémonos en que MANUEL PALOMAR, que no imparte ninguna de las asignaturas objeto de la búsqueda, tampoco aparece en la tabla resultado puesto que su dni no aparece en la tabla IMPARTE.

En realidad, no es más que una forma más compacta —y cómoda— de describir condiciones lógicas. Las consultas anteriores son equivalentes a, respectivamente :

select descripcion from asignaturas

where codigo = 'FBD' OR codigo = 'DGBD';


select nombre from profesores p, imparte i where p.dni = i.dni

and NOT(asignatura='HI' OR asignatura='FBD' OR asignatura='DGBD');

En esta última consulta, también podríamos haber transformado la negación como:

select nombre from profesores p, imparte i where p.dni = i.dni

and (asignatura != 'HI' AND asignatura != 'FBD' AND asignatura != 'DGBD')

(Que "asignatura" sea distinta de 'HI', y distinta de 'FBD', y distinta de 'DGBD')

Consultas anidadas y listas de valores

Hemos visto que puedo sustituir varias expresiones conectadas por OR con una lista de constantes. ¿Y si generamos esa lista de constantes desde otra consulta select? Estamos entrando en un área un poco más compleja que es la de la consultas anidadas o subconsultas. De momento, vamos a quedarnos con una de las situaciones más simples y que puede resultar hasta intuitiva.

expr [NOT] IN (orden select)

Una consulta como select dni from imparte solo va a producir una columna con 0 o varias filas. —en nuestro caso, sin eliminar duplicados, 3 filas—. Aunque nosotros lo vemos como una lista "vertical" de valores, en realidad no tiene por qué ser así.

Supongamos que planteamos la siguiente consulta:

select * from profesores where dni='21111222' OR dni='21111222' OR dni='21333444'

Es evidente que una de las expresiones es redundante, pero estamos tratando de que se vea la idea detrás de lo que se desarrollará a continuación. Como hemos visto, esas expresiones lógicas se pueden expresar de forma más compacta con:

select * from profesores where dni IN ('21111222', '21111222', '21333444')

Pues SQL nos permite obtener esa lista del IN directamente con una consulta.

select * from profesores where dni IN (select dni from imparte)

La principal aplicación de este tipo de órdenes es recuperar datos de nuestra base de datos que, eventualmente, pueden cambiar con el tiempo. En ese aspecto, es una consulta "dinámica", su resultado puede ser distinto según el momento en el que la ejecutemos.

Obtener todos los datos de los profesores que imparten alguna asignatura.

select * from profesores

where dni IN (select dni from imparte)

O dicho de otra manera: "datos de los profesores cuyo dni aparece en la tabla imparte".

En este caso daría lo mismo procesar la orden

select distinct p.*

from profesores p, imparte i

where p.dni = i.dni

NOTA: usar IN de esta manera no genera filas duplicadas, consigue el mismo resultado que el modificador distinct de la segunda consulta. Mientras que IN va recorriendo la tabla PROFESORES y preguntando uno a uno si se encuentra en la tabla IMPARTE o no, la segunda realiza el producto cartesiano y descarta las filas en las que no coinciden los valores de DNI. Eso genera filas duplicadas que se eliminan con distinct.

Se verá más clara la utilidad de este operador si preguntamos justo lo contrario.

Obtener todos los datos de los profesores que no imparten asignaturas.

select * from profesores

where dni NOT IN (select dni from imparte)

¡Cuidado!

La orden anterior no es equivalente a

select distinct p.*

from profesores p, imparte i

where p.dni != i.dni;

Lo que debes preguntarte es ¿porqué?

Piénsalo como te hemos dicho en otras ocasiones:

  1. from

  2. where

  3. select

P02 operador distinto.pdf