Ir al contenido principal

Subquerys Correlacionados.

Un Subqyuery Correlacionado tiene un método más complejo de ejecución que un Subquery Single-Row y un Multiple-Row y es potencialmente más poderoso. Si un Subquery hace referencia a columnas de la consulta padre, entonces el resultado será dependiente de la consulta padre. Esto hace imposible evaluar el subquery antes  de la evaluación de la consulta padre.
El Subquery Single-Row necesita ser ejecutado solo una vez, y el resultado es sustituido en la consulta padre. Pero ahora considere una consulta que desplegara todos los empleados que su salario es menor que el salario promedio de su departamento. En este caso, el subquery debe ser ejecutado por cada empleado para determinar el promedio de salario de su departamento; es necesario pasar el id de departamento al subquery. Esto puede ser realizado como sigue:

SELECT e1.employee_id,
       e1.first_name,
       e1.last_name,
       e1.department_id,
       e1.salary,
       (SELECT ROUND(AVG(e2.salary)) FROM employees e2  WHERE E2.department_id = e1.department_id) PROMEDIO_DEPARTAMENTO
FROM   employees e1
WHERE  e1.salary < (SELECT ROUND(AVG(e2.salary)) FROM employees e2  WHERE E2.department_id = e1.department_id)
ORDER BY e1.employee_id;

En esta consulta el Subquery referencia las columna DEPARTMENT_ID de la consulta padre, esto es señal que el subquery debe ser evaluado una vez por cada empleado. El subquery se ejecutara utilizando el DEPARTMENT_ID de cada empleado.

La ejecución se realiza en el siguiente orden:
1.       Inicia en la primera fila de la tabla EMPLOYEES.
2.       Lee el DEPARTMENT_ID y SALARY de la fila actual.
3.       Ejecuta el Subquery utilizando el DEPARMENT_ID del paso 2.
4.       Compara el resultado del paso 3 con el SALARY del paso 2 y devuelve la fila si el SALARY es menor que el resultado.
5.       Avanza a la siguiente fila de la tabla EMPLOYEES.
6.       Y repite el paso 2.

Un Subquery Single-Row o Multiple-Row es evaluado una vez, antes de ser evaluado la consulta padre. Un Subquery Correlacionado debe ser evaluado una vez por cada fila de la consulta padre. Un Subquery Correlacionado puede ser un Single o Multiple Row. Si los operadores de comparación son los apropiados.

SELECT employee_id, first_name, last_name, salary, (SELECT salary FROM employees WHERE UPPER(last_name) LIKE '%TOBIAS%') salary_tobias
FROM   employees
WHERE  salary > (SELECT salary FROM employees WHERE UPPER(last_name) LIKE '%TOBIAS%')
ORDER BY employee_id;

SELECT employee_id, first_name, last_name, salary, (SELECT salary FROM employees WHERE UPPER(last_name) LIKE '%TAYLOR%') salary_tobias
FROM   employees
WHERE  salary > (SELECT salary FROM employees WHERE UPPER(last_name) LIKE '%TAYLOR%')
ORDER BY employee_id;

SELECT employee_id, first_name, last_name, salary, (SELECT MAX(salary) FROM employees WHERE UPPER(last_name) LIKE '%TAYLOR%') salary_tobias
FROM   employees
WHERE  salary > ALL (SELECT salary FROM employees WHERE UPPER(last_name) LIKE '%TAYLOR%')
ORDER BY employee_id;

SELECT employee_id, first_name, last_name, salary, (SELECT MAX(salary) FROM employees WHERE UPPER(last_name) LIKE '%TAYLOR%') salary_tobias
FROM   employees
WHERE  salary > (SELECT MAX(salary) FROM employees WHERE UPPER(last_name) LIKE '%TAYLOR%')
ORDER BY employee_id;

SELECT employee_id, first_name, last_name
FROM   employees
WHERE  manager_id IN (
                        SELECT e.employee_id
                        FROM   employees e
                               JOIN departments d ON (e.department_id = d.department_id)
                               JOIN locations   l ON (d.location_id = l.location_id)
                               JOIN countries   c ON (l.country_id = c.country_id)
                        WHERE  c.country_name = 'United Kingdom'
                     );

SELECT employee_id, first_name, last_name
FROM   employees
WHERE  manager_id IN (
                       SELECT employee_id
                       FROM   employees
                       WHERE  department_id IN (
                                                 SELECT department_id
                                                 FROM   departments
                                                 WHERE  location_id IN (
                                                                          SELECT location_id
                                                                          FROM   locations
                                                                          WHERE  country_id = 'UK'
                                                                       )
                                               )
                      
                     );


SELECT job_title
FROM   jobs
       NATURAL JOIN employees
GROUP BY job_title

HAVING AVG(salary) = (SELECT MAX(AVG(salary)) FROM employees GROUP BY job_id);

Comentarios