consultas anidadas - BUCOMSEC

Anuncio
prácticas BD1 2003-04
sesión 13
CONSULTAS ANIDADAS
Objetivos:
•
Utilizar el resultado de una sentencia select para establecer las condiciones de otra sentencia
select.
Contenidos
•
Subqueries.
•
operadores de comparación escalar.
•
IN, ALL, ANY, [NOT].
•
Resolución de requerimientos.
CONSULTAS ANIDADAS (SUBQUERIES)
En la condición de búsqueda de la orden select (en la cláusula where o en la having) también
podemos:
• comparar una expresión con el resultado de otra orden select
• determinar si el valor de una expresión está incluido en los resultados de otra orden select
• preguntar si una orden select ha seleccionado filas.
Cuando una orden select se encuentra dentro de la cláusula where de otra select recibe el nombre
de subconsulta (subquery). Por ejemplo :
select descripción, créditos
from asignaturas
where créditos = ( select min(créditos) from asignaturas )
resultado:
descripción
Historia de la Informática
créditos
4.5
En primer lugar se calcula la select anidada (entre paréntesis) y se obtiene el valor mínimo para la
columna créditos de la tabla asignaturas. Con ese valor se compara tupla a tupla y se obtiene la
asignatura (o asignaturas) cuya cantidad de créditos es igual al mínimo.
sintaxis general de la subconsulta
expresión op_comparación { ALL | [ ANY | SOME ] } ( orden select )
expresión [ NOT ] IN ( orden select )
[ NOT ] EXISTS ( orden select )
Los valores posibles a devolver por una orden select anidada son :
•
nada
•
un valor único (una fila y una columna),
•
un conjunto de valores (varias filas y una columna).
75
prácticas BD1 2003-04
Siempre que la subselect devuelva algo, únicamente será en una y nada más que una
columna (salvo el operador EXISTS).
DEVOLUCIÓN DE UN ÚNICO VALOR
expresión op_comparación ( orden select )
Podemos utilizar los operadores de comparación para preguntar si el valor de una determinada
expresión es mayor, menor, igual, etc. que el resultado de la subselect, siempre y cuando ésta
devuelva una única fila y una única columna, es decir, un valor simple.
En general serán órdenes select que calculan una función agregada (sum, min, max, avg, count).
select descripción
from asignaturas
where créditos = ( select min(créditos) from asignaturas )
No sería correcto, porque la subselect devuelve más de una fila, la siguiente orden :
select descripción
from asignaturas
where créditos = ( select créditos from asignaturas where créditos < 9 )
DEVOLUCIÓN DE UNA LISTA DE VALORES
expresión op_comparación ALL | [ ANY | SOME ] ( orden select )
Cuando la tabla resultado contiene más de una fila (pero una única columna, insistimos) hay que
utilizar un modificador para el operador de comparación.
Nombre de la asignatura que tiene el mínimo número de créditos (es equivalente al primer
ejemplo) :
select descripción
from asignaturas
where créditos <= ALL ( select créditos from asignaturas )
resultado:
descripción
Historia de la Informática
créditos
4.5
En este caso, el número en créditos de la asignatura tiene que ser menor o igual que todos (all) los
valores obtenidos en la subconsulta (que es la relación de créditos de todas las asignaturas).
76
prácticas BD1 2003-04
Nombre de las asignaturas que no tienen el mínimo número de créditos :
select descripción
from asignaturas
where créditos > ANY ( select créditos from asignaturas )
resultado:
créditos
6
6
6
9
descripción
Fundamentos de las Bases de Datos
Diseño y Gestión de Bases de Datos
Programación Concurrente
Fundamentos de la Programación
Serían todas aquellas asignaturas cuyos créditos superasen al menos a uno (any) de los valores
devueltos por la subconsulta. El modificador some es equivalente a any.
Otra forma de expresar el mismo requerimiento :
select descripción
from asignaturas
where créditos != ( select min(créditos) from asignaturas )
Supongamos que deseamos obtener el nombre de los profesores que imparten una asignatura que
no sea la máxima en número de créditos :
select nombre
from profesores p, asignaturas a, imparte i
where p.dni = i.dni and i.asignatura = a.codigo
and créditos < ANY ( select créditos from asignaturas )
resultado:
nombre
Eva Gómez
Rafael Romero
expresión [ NOT ] IN ( orden select )
También podemos consultar la pertenencia de un valor a la lista de valores devuelta por la
subconsulta.
Obtener todos los datos de los profesores que imparte 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 p.* from profesores p, imparte i
where p.dni = i.dni
Se verá más clara la utilidad de este operador si preguntamos justo lo contrario.
77
prácticas BD1 2003-04
Obtener todos los datos de los profesores que no imparten asignaturas :
select * from profesores
where dni NOT IN ( select dni from imparte )
Por último, veamos que algunos de estos operadores son equivalentes :
expresión IN (orden select)
expresión NOT IN (orden select)
78
≡
≡
expresión =ANY (orden select)
expresión !=ALL (orden select)
prácticas BD1 2003-04
REQUERIMIENTOS S13
1.
Obtener todos los datos de los vendedores a los que se les han solicitado más pedidos que a
todos los demás.
2.
Número y nombre de los vendedores que no ofertan ninguna pieza.
3.
Número y nombre de los vendedores a los que se les ha solicitado algún pedido.
4.
Número y nombre de los vendedores a los que no se les ha solicitado pedidos.
5.
Nombre de la empresa que ofrece la pieza más barata de precio de suministro.
6.
Número y descripción de la pieza más cara (precio de venta).
7.
Para cada pieza que se ofrece en la lista de suministros, obtener el número de pieza, y sus
precios unitarios máximo y mínimo, exceptuando aquellos suministrados por el vendedor
número 1.
8.
Número de pedido y precio total pagado del pedido más caro.
9.
Número y nombre del vendedor al que se le ha solicitado el pedido más caro.
10. Número, descripción y precio de venta de los monitores que no han sido nunca solicitados.
11. Calcular, por cada número de vendedor, la cantidad de piezas distintas que ha vendido, para
aquellos vendedores pertenecientes a la empresa con más proveedores.
12. Nombre de los suministradores que pueden suministrar al menos alguna de las piezas que
puede suministrar el vendedor número 5.
13. Listar los vendedores que sean de la misma provincia que el vendedor número 100.
14. Obtener los nombres de los vendedores de la misma empresa que Luis García.
15. Número y descripción de las piezas cuyo precio medio de suministro esté por encima del mayor
precio de compra pagado por ella.
16. Número, nombre, empresa en la que trabaja y número de piezas que puede suministrar el
vendedor que tiene la media más alta de piezas servidas.
17. Nombre de la empresa con mayor importe de ventas.
18. Número y descripción de la pieza que ha sido pedida más veces.
19. Número y descripción de las piezas que pueden ser suministradas por proveedores de la
Comunidad Valenciana o que pueden ser suministradas por el vendedor que ha realizado la
menor venta (pedido de importe más bajo)
20. Número de vendedor, número de pieza y descuento para aquellas piezas cuyo precio de venta
supere en más del 15% la media del precio de compra de los pedidos en los que aparece.
21. Cantidad de piezas a la venta de las que no tenemos información sobre sus posibles
suministradores.
79
prácticas BD1 2003-04
SOLUCIONES S13
--1
select *
from vendedor
where numvend in (select numvend
from pedido
group by numvend
having count(*) >= all(select count(*)
from pedido
group by numvend))
--2
select numvend, nomvend
from vendedor
where numvend not in (select numvend
from preciosum)
order by nomvend
En A.R. (VENDEDOR[numvend] ∼ PRECIOSUM[numvend]) ><
VENDEDOR[numvend, nomvend]
En C.R.T.
{V.numvend, V.nomvend / VENDEDOR(V) ∧  ∃
PR(PRECIOSUM(PR) ∧ PR.numvend=V.numvend)}
--3a
select v.numvend, nomvend
from vendedor v, pedido p
where v.numvend = p.numvend
order by nomvend
En A.R. VENDEDOR >< PEDIDO [numvend, nomvend]
En C.R.T.
{V.numvend, V.nomvend / VENDEDOR(V) ∧ ∃ P(PEDIDO(P)
∧ P.numvend=V.numvend)}
--3b
select numvend, nomvend
from vendedor
where numvend in (select numvend
from pedido)
order by nomvend
--11
select v.numvend,count(distinct numpieza) npiezas
from vendedor v, pedido p, linped l
where v.numvend=p.numvend
and p.numpedido=l.numpedido
and nombrecomer in
(select nombrecomer
from vendedor
group by nombrecomer
having count(*) >= all
(select count(*)
from vendedor
group by nombrecomer))
group by v.numvend
order by v.numvend
--15
select p.numpieza, nompieza,avg(preciounit),max(preciocompra)
from pieza p, preciosum ps, linped l
where p.numpieza=ps.numpieza and ps.numpieza=l.numpieza
group by p.numpieza, nompieza
having avg(preciounit)>=
(select max(preciocompra)
from linped
where linped.numpieza=p.numpieza)
80
sesión 14
CONSULTAS ANIDADAS II
Contenidos
•
El operador EXISTS.
•
Resolución de requerimientos.
EL OPERADOR EXISTS
[ NOT ] EXISTS ( orden select )
El operador exists nos informa si una subconsulta ha devuelto algún resultado, o lo que es lo
mismo, si la tabla resultado tiene alguna fila.
Exists devuelve verdadero si hay al menos una tupla en la relación derivada y falso si la relación
derivada es vacía.
Supongamos que queremos conocer si algún profesor imparte todas las asignaturas :
select nombre from profesores p
where not exists ( select código from asignaturas a
where not exists ( select asignatura from imparte i
where i.asignatura=a.código and p.dni=i.dni ) )
Vamos a leer el requerimiento siguiendo las apariciones del operador exists dentro de las sucesivas
órdenes select : Nombre de los profesores tales que no hay ninguna asignatura que no imparta él.
Supongamos que la forma que tiene el SGBD de resolver esta sentencia es la siguiente :
•
En la primera select recorremos la tabla de profesores.
•
Para cada profesor, la segunda select recorre la tabla de asignaturas.
•
Para cada profesor y asignatura comprueba que el primero imparte la segunda.
Una vez que ha fijado el profesor y la asignatura, la última subconsulta dará como resultado
verdadero si la imparte y falso en caso contrario (devolverá una tupla o no devolverá nada).
Supongamos un profesor que no imparte al menos una de las asignaturas de nuestra base de datos.
Cuando el SGBD esté resolviendo la última subselect para ese profesor y esa asignatura, como no están
relacionados, no devolverá ninguna tupla : el resultado del segundo exists es falso, y, como está
negado, finalmente verdadero (ese profesor no imparte esa asignatura).
Por lo tanto, para la primera subselect, ya existe una asignatura que obtiene en la cláusula where un
valor verdadero : esa asignatura saldrá en la tabla resultado. Como ésta última tiene al menos una fila,
el primer exists será verdadero, y, como está negado, finalmente falso. El profesor no imparte todas las
asignaturas de nuestra base de datos.
Un profesor que imparta todas las asignaturas obtendrá siempre una fila en la última subselect y, por
lo tanto, ninguna asignatura aparecerá como resultado de la primera subselect, el correspondiente
exists será falso, y por efecto del operador de negación la condición será cierta : ese profesor aparecerá
en la solución.
En nuestra base de datos Ejemplo no hay ningún profesor que imparta todas las asignaturas.
prácticas
Aunque puede inducir a error, por su traducción intuitiva del inglés al español, no se
deben confundir nunca los operadores IN y EXISTS : el primero devuelve una lista de valores,
mientras que el segundo devuelve un valor de verdad; la sintaxis también es muy diferente.
82
prácticas
REQUERIMIENTOS S14
1.
Nombre de los vendedores que pueden suministrar todas las piezas.
2.
Nombre de los
alfabéticamente.
3.
Numero y descripción de las piezas que se han solicitado en todos los pedidos del vendedor 1.
4.
Nombre de las empresas que cumplen que todos sus vendedores son de la Comunidad
Valenciana, ordenadas alfabéticamente.
5.
Número y nombre de todos los vendedores de la ciudad de Alicante.
6.
Empresas que no han servido ninguna pieza.
7.
Empresas que han servido la(s) pieza(s) de mayor precio de venta.
8.
Numero de los pedidos cuyas piezas tienen todas un precio de venta mayor que la mitad del
precio máximo de venta.
9.
Obtener todos los datos de los vendedores que sirvieron los pedidos del requerimiento anterior.
vendedores
que no
pueden suministrar ninguna pieza, ordenados
10. Número y nombre de los vendedores que han servido algún pedido (utilizando obligatoriamente
EXISTS).
11. Número y nombre de la pieza de menor precio de suministro (utilizando EXISTS).
12. Nombre de los vendedores a los que se les haya solicitado más de dos pedidos (utilizando
subconsultas).
13. Número de pedido, fecha y número de vendedor del pedido más caro (utilizando subconsultas).
83
prácticas
SOLUCIONES S14
--1
select nomvend
from vendedor v
where not exists
(select *
from pieza pz
where not exists
(select *
from preciosum
where numvend = v.numvend and numpieza = pz.numpieza))
En A.R. ((PRECIOSUM [numvend, numpieza] ÷ PIEZA[numpieza]) ><
VENDEDOR) [nomvend]
En C.R.T.
{ V.nomvend / VENDEDOR(V) ∧ ∀P (PIEZA(P) ⇒ ∃ PR
(PRECIOSUM(PR) ∧ PR.numvend=V.numvend ∧ PR.numpieza=P.numpieza ))}
--2
select nomvend
from vendedor
where numvend not in (select numvend
from preciosum)
order by nomvend
--2
select nomvend
from vendedor v
where not exists (select *
from preciosum
where numvend = v.numvend)
order by nomvend
En A.R. ((VENDEDOR[numvend] ∼ PRECIOSUM[numvend]) ><
VENDEDOR)[nomvend]
En C.R.T.
{V.nomvend / VENDEDOR(V) ∧  ∃ PR(PRECIOSUM(PR) ∧
PR.numvend=V.numvend)}
--3
select numpieza, nompieza
from pieza pz
where not exists
(select *
from pedido pd
where numvend=1
and not exists (select *
from linped l
where pd.numpedido=l.numpedido
and pz.numpieza=l.numpieza))
En A.R. ((LINPED [numpieza, numpedido] ÷ (PEDIDO donde
numvend=1)[numpedido]) >< PIEZA) [numpieza, nompieza]
En C.R.T.
{ P.numpieza, P.nompieza / PIEZA(P) ∧ ∀PD
(PEDIDO(PD) ∧ PD.numvend=1 ⇒ ∃ LP (LINPED(LP) ∧
LP.numpedido=PD.numpedido ∧ LP.numpieza=P.numpieza ))}
--4
select distinct nombrecomer
from vendedor v
where not exists
(select *
from vendedor
where nombrecomer = v.nombrecomer
and provincia not in ('ALICANTE','CASTELLON','VALENCIA'))
order by nombrecomer
En A.R. VENDEDOR[nombrecomer] ∼ (VENDEDOR donde provincia<>ALICANTE
or provincia<>CASTELLON or provincia<>VALENCIA)[nombrecomer]
En C.R.T.
{ V.nombrecomer / VENDEDOR(V) ∧ ∀ V2 (VENDEDOR(V2)
∧ V2.nombrecomer=V.nombrecomer ⇒ (V2.provincia=ALICANTE ∨
V2.provincia=CASTELLON ∨ V2.provincia=VALENCIA))}
O bien
{ V.nombrecomer / VENDEDOR(V) ∧  ∃ V2 (VENDEDOR(V2) ∧
V2.nombrecomer=V.nombrecomer ∧ V2.provincia<>ALICANTE ∧
V2.provincia<>CASTELLON ∧ V2.provincia<>VALENCIA))}
84
Descargar