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:
from
where
select