EXISTS y NOT EXISTS

Anuncio
EMPLEADO(dni,nombree,direccion,
sexo,salario,fecha_nac,dni_super↑,numerod↑)
DEPARTAMENTO(numerod,nombred,dni_dir↑,
fecha_ini)
PROYECTO(numerop,nombrep,lugar,numerod↑)
TRABAJA_EN(dni↑,numerop↑,horas)
54
EXISTS y NOT EXISTS
Empleados que no trabajan en el proyecto 527.
SELECT dni
FROM TRABAJA_EN
WHERE numerop <> 527
SELECT dni
FROM EMPLEADO
WHERE NOT EXISTS
(SELECT *
FROM TRABAJA_EN
WHERE TRABAJA_EN.dni = EMPLEADO.dni AND numerop = 527)
55
1
EXIST y NOT EXISTS (II)
„
„
„
„
Siempre preceden a subconsulta
EXISTS - cierto si el conjunto resultante
de la subconsulta no está vacío
NOT EXISTS - cierto si vacío
En el ejemplo la subconsulta selecciona todas
las filas de TRABAJA_EN que tienen el mismo
NSS que la fila que se está examinando en la
consulta principal y el NUMEROP igual a 527.
Si ese conjunto está vacío, se selecciona la
fila correspondiente
56
EXISTS y NOT EXISTS (III)
Lo anterior era consulta correlacionada.
Si queremos no correlacionada
SELECT dni
FROM EMPLEADO
WHERE dni NOT IN
(SELECT dni
FROM TRABAJA_EN
WHERE numerop = 527)
57
2
EXISTS y NOT EXISTS (IV)
¿Por qué usar NOT EXISTS? Única forma de expresar consultas que
contengan el cuantificador “todos” - Ejemplo: empleados que
trabajan en todos los proyectos = empleados tales que no hay
ningún proyecto en el que no trabajen
1. Proyectos en los que el empleado 1234 no trabaja
SELECT nombrep
FROM PROYECTO
WHERE NOT EXISTS
(SELECT *
FROM TRABAJA_EN
WHERE TRABAJA_EN.numerop = PROYECTO.numerop
AND TRABAJA_EN.dni = 1234)
58
EXISTS y NOT EXISTS (V)
2. Generalizar la consulta a un NSS variable
SELECT nombree
FROM EMPLEADO
WHERE NOT EXISTS
(SELECT *
FROM PROYECTO
WHERE NOT EXISTS
(SELECT *
FROM TRABAJA_EN
WHERE TRABAJA_EN.numerop = PROYECTO.numerop
AND TRABAJA_EN.dni = EMPLEADO.dni)
„
Proyectos en los que el
empleado X no está
trabajando.
Si vacío ⇒ nos vale ese
empleado
NOT EXISTS puede usarse para expresar los tipos de consultas
para los que se utiliza el operador división del álgebra relacional
59
3
Ejemplos (I)
Si el departamento 122 está ubicado en la calle de Alcalá, obtener por
orden alfabético los nombres de aquéllos de sus empleados cuyo
salario supere al salario medio de su departamento.
SELECT nomem
FROM EMPLEADO
WHERE numde = 122 AND
salario > (SELECT AVG(salario) FROM EMPLEADO
WHERE numde = 122) AND
EXISTS (SELECT *
FROM DEPARTAMENTO
WHERE numde = 122 AND numce IN
(SELECT numce
FROM CENTRO
WHERE señas LIKE ‘%ALCALA%’)
ORDER BY nomem
60
El operador UNIQUE
„
Cierto si no hay dos filas iguales en la tabla
Empleados que trabajan en más de un proyecto
SELECT DISTINCT apellido
FROM EMPLEADO
WHERE NOT UNIQUE
(SELECT nump
FROM TRABAJA_EN
WHERE TRABAJA_EN.nsse = EMPLEADO.nss)
61
4
El operador MATCH
„
fila MATCH [UNIQUE] tabla
Cierto si existe al menos una fila en la tabla igual a
fila. (Si aparece UNIQUE - exactamente una fila)
Empleados que no tienen un departamento válido
SELECT nomem
FROM EMPLEADO
WHERE NOT (EMPLEADO.numde MATCH UNIQUE
(SELECT numde
FROM departamento))
62
Tablas anidadas
Hallar los departamentos y el número de empleados que tienen
aquellos en los que la media de los salarios de sus empleados sea
inferior a 2900 euros.
SELECT numerod, totalemp
FROM
(SELECT A.numde AS numerod, AVG(salario) AS salmedio,
COUNT(*) AS totalemp
FROM EMPLEADO NJ DEPARTAMENTO
GROUP BY numde) AS XXX
WHERE salmedio < 2900
ORDER BY numerod
„
Es obligatorio asignarle un nombre a la tabla anidada
63
5
Tablas anidadas (II)
Para los departamentos 100 y 110, hallar el valor medio de los
salarios medios por departamento.
SELECT AVG(premed) AS MEDIA
FROM
(SELECT AVG(salario) AS PREMED
FROM EMPLEADO
WHERE numde IN (100, 110)
GROUP BY numde) AS T1
64
Tablas anidadas (III)
Construir dos grupos con los departamentos. Uno con aquellos en los que el presupuesto es
superior en 10 veces a la suma de los salarios de sus empleados y otro con los que es
inferior. Hallar para cada grupo el presupuesto medio.
SELECT GRUPO, AVG(pres) AS PREMEDIO
FROM
(SELECT presupuesto*1000 AS PRES, `MAYOR’ AS GRUPO
FROM DEPARTAMENTO D1
WHERE presupuesto*1000 > (SELECT SUM(salario) * 10
FROM EMPLEADO E1
WHERE E1.numde = D1.numde)
UNION ALL
SELECT presupuesto*1000 AS PRES, `MENOR’ AS GRUPO
FROM DEPARTAMENTO D2
WHERE presupuesto*1000 > (SELECT SUM(salario) * 10
FROM EMPLEADO E2
WHERE E2.numde = D2.numde)
) AS GRUPOS
GROUP BY GRUPO
ORDER BY GRUPO
65
6
Tablas anidadas (IV)
Hallar para los departamentos del centro 10, su número, su
presupuesto y la suma de salarios de sus empleados.
SELECT A.numde AS NUMDEP, presupuesto, SUMSALAR
FROM DEPARTAMENTO A,
TABLE (SELECT SUM(salario) AS SUMSALAR
FROM EMPLEADO B
WHERE B.numde = A.numde) AS XXX
WHERE numce = 10
ORDER BY NUMDEP
66
Equivalente a
Hallar para los departamentos del centro 10, su número, su
presupuesto y la suma de salarios de sus empleados.
SELECT A.numde AS NUMDEP, presupuesto, SUMSALAR
FROM DEPARTAMENTO A,
(SELECT numde, SUM(salario) AS SUMSALAR
FROM EMPLEADO
GROUP BY numde) AS T1
WHERE numce = 10 AND A.numde = T1.numde
ORDER BY NUMDEP
67
7
Y También a
Hallar para los departamentos del centro 10, su número, su
presupuesto y la suma de salarios de sus empleados.
SELECT numde, presupuesto, SUM(salario) AS SUMSALAR
FROM DEPARTAMENTO NJ EMPLEADO
WHERE numce = 10
GROUP BY numde, presupuesto
ORDER BY numde
68
Tablas anidadas (V)
SELECT numem
FROM (SELECT numem, fecna, salario
FROM (SELECT *
FROM EMPLEADO
WHERE numde = 121) AS T1
WHERE salario < 5000 ) AS T2
WHERE fecna < ‘1950-01-01’
ORDER BY numem
SELECT numem
FROM EMPLEADO
WHERE numde = 121 AND salario < 5000
AND fecna < `1950-01-01’
ORDER BY numem
69
8
Referencias correlacionadas
„
„
Cuando en una subconsulta se especifica un nombre
de columna, el SGBD debe saber sin ambigüedad en
qué tabla se encuentra esta columna a la que nos
referimos.
Para ello el sistema busca la primera tabla que
contenga una columna con el nombre especificado
siguiendo el siguiente orden
¾ Las tablas que aparecen antes en la propia
cláusula FROM de la sentencia correlacionada
¾ Las tablas de la cláusula FROM de la primera
sentencia antecedente
¾ Se recorren consecutivamente las tablas
antecedentes hasta llegar a la sentencia externa
70
Referencias correlacionadas (II)
„
„
„
En tablas anidadas si queremos que la búsqueda se
realice hacia los niveles superiores hay que poner la
palabra TABLE.
Si no se pone TABLE, se limita la búsqueda a las
tablas de la propia cláusula FROM
Ejemplo válido: referencia correlacionada T1.C1
SELECT T1.C1, T3.C3
FROM T AS T1,
TABLE (SELECT * FROM T AS T2 WHERE T2.C1 = T1.C1) AS T3
WHERE T1.C2 = T3.C2
71
9
Referencias correlacionadas (III)
„
Ejemplo inválido: referencia correlacionada T1.C1
SELECT T1.C1, T3.C3
FROM TABLE (SELECT * FROM T AS T2 WHERE T2.C1 = T1.C1) AS T3,
T AS T1
WHERE T1.C2 = T3.C2
„
Ejemplo inválido: referencia correlacionada T1.C1
SELECT T1.C1, T3.C3
FROM T AS T1,
(SELECT * FROM T AS T2 WHERE T2.C1 = T1.C1) AS T3
WHERE T1.C2 = T3.C2
72
Referencias correlacionadas (IV)
Hallar para los departamentos del centro 10, su número, su
presupuesto y la suma de salarios de sus empleados.
SELECT A.numde, presupuesto, SUMSALAR
FROM DEPARTAMENTO A,
TABLE (SELECT SUM(salario) AS SUMSALAR
FROM EMPLEADO B
WHERE B.numde = A.numde) AS XXX
WHERE numce = 10
ORDER BY numde
referencia correlacionada: A.numde
73
10
Descargar