•Definir las subconsultas.
•Describir los tipos de problemas que pueden resolver con las subconsultas.
•Enumerar los tipos de subconsultas.
•Escribir subconsultas de una sola fila y de varias filas.
•Describir los tipos de problemas que pueden resolver con las subconsultas.
•Enumerar los tipos de subconsultas.
•Escribir subconsultas de una sola fila y de varias filas.
NOTA: Usamos como ejemplo la base de datos: ORCL, la cual viene por defecto en cualquier versión de ORACLE.
_____________________________________________________________________________________
SubConsultas o Sentencias SELECT Anidadas.
SubConsultas o Sentencias SELECT Anidadas.
Las Subconsultas se podrían considerar unas de las funciones más avanzadas de la sentencia SELECT. Básicamente consisten en escribir consultas en la cláusula WHERE de otra sentencia SQL para obtener valores basados en un valor condicional desconocido.
Por ejemplo, si queremos saber todos los empleados que trabajan en mismo departamento que el empleado Zlotkey, tendremos primero que determinar cual es el departamento del empleado Zlotkey.
Para ello podríamos hacer una consulta en la cual retornemos el numero de departamento de Zlotkey y juego otra para ver todos los empleados que trabajan ahí.
Una forma mas eficiente seria combinando las dos consultas, colocando una consulta dentro de la otra consulta. La consulta interna (o subconsulta) devuelve un valor que se utiliza en la otra consulta (o consulta principal).
Sintaxis:
SELECT select_list
FROM table
WHERE expr operator
(SELECT select_list
FROM table);
Definición:
•La subconsulta (consulta interna) se ejecuta una vez antes de la consulta principal (consulta externa).
•La consulta principal utiliza el resultado de la subconsulta.
•operator incluye una condición de comparación como, por ejemplo, >, = o IN.
•La subconsulta se suele conocer como sentencia SELECT anidada, subSELECT o SELECT interna. •La subconsulta se ejecuta en primer lugar y se utiliza su salida para completar la condición de restricción para la consulta principal (o externa).
•Las consultas externas e internas pueden obtener datos de tablas diferentes.
Algunas Directrices:
•Las subconsultas deben ir entre paréntesis.
•Sitúe las subconsultas a la derecha de la condición de comparación para que se
lean mejor.
•Con Oracle8i y versiones posteriores, se puede utilizar una cláusula ORDER BY y es necesaria en la subconsulta para realizar análisis de los N principales.
-Antes Oracle8i, sin embargo, las subconsultas no podían contener una cláusula ORDER BY. Sólo se podía utilizar una cláusula ORDER BY para una sentencia SELECT; si se especificaba, tenía que ser la última cláusula de la sentencia SELECT principal.
•Se utilizan dos clases de condiciones de comparación en las subconsultas: operadores de
una sola fila y operadores de varias filas.
_____________________________________________________________________________________
Tipos de SubConsultas.
•SubConsultas de una sola fila: Son las Consultas en las cuales el Query o SELECT interno solo retorna una fila como resultado.
•SubConsultas de varias filas: En estas el Query interno retorna mas de una fila como resultado.
Nota: También hay subconsultas de varias columnas, que son consultas que devuelven más de una columna de la sentencia SELECT interna. Dichas subconsultas serán explicadas en futuras publicaciones.
SubConsultas de una sola fila.
•Devuelven sólo una fila.•Utilizan operadores de comparación de una sola fila:
Operador | Significado |
= | Igual que |
> | Mayor que |
>= | Mayor o igual que |
< | Menor que |
<= | Menor o igual que |
<> | Distinto de |
SELECT last_name, job_id
FROM employees
WHERE job_id =
(SELECT job_id
FROM employees
WHERE employee_id = 141);
/*El Query anterior nos sirve para determinar los empleados que tienen el mismo tipo de trabajo que el empleado 141.*/
---
SELECT last_name, job_id, salary
FROM employees
WHERE job_id =
(SELECT job_id
FROM employees
WHERE employee_id = 141)
AND salary >
(SELECT salary
FROM employees
WHERE employee_id = 143);
/*El Query anterior nos retorna todos los empleados que tienen el mismo tipo de puesto que el empleado 141 y que también ganan mas que el empleado 143.
Dicho Query contiene 3 consultas: la consulta externa y 2 internas. Los bloques de consultas internas se ejecutan en primer lugar, con lo que se crean los resultados de consulta ST_CLERK y 2600, respectivamente. A continuación se procesa el bloque de la consulta externa, utilizando los valores que devolvieron las consultas internas para completar sus condiciones de búsqueda.*/
---
SELECT last_name, job_id, salary
SELECT last_name, job_id, salary
FROM employees
WHERE salary =
(SELECT MIN(salary)
FROM employees);
/*El Query anterior muestra los o el empleado que gana el salario mínimo de la empresa. Como vemos es posible usar una función de grupo en el /Query interno de una SubConsulta.*/
---
SELECT department_id, MIN(salary)
FROM employees
HAVING MIN(salary) >
(SELECT MIN(salary)
FROM employees
WHERE department_id = 10);
/*Este Query muestra los departamentos cuyo salario mínimo es mayor al salario mínimo del departamento 10. Vemos que es posible usar una SubConsulta en la cláusula HAVING de otra otra consulta.*/
---
SubConsultas de varias filas.
Un error común en las subconsultas se produce cuando se devuelve más de una fila para una subconsulta de una sola fila. En los casos que se usa un operador de comparación como (=,>,< etc.) y la subconsulta retorna mas de una fila un error es retornado al usuario, Para corregir este error, cambie el operador = a IN.
FROM employees
GROUP BY department_id
HAVING MIN(salary) >
(SELECT MIN(salary)
FROM employees
WHERE department_id = 10);
/*Este Query muestra los departamentos cuyo salario mínimo es mayor al salario mínimo del departamento 10. Vemos que es posible usar una SubConsulta en la cláusula HAVING de otra otra consulta.*/
---
SubConsultas de varias filas.
Un error común en las subconsultas se produce cuando se devuelve más de una fila para una subconsulta de una sola fila. En los casos que se usa un operador de comparación como (=,>,< etc.) y la subconsulta retorna mas de una fila un error es retornado al usuario, Para corregir este error, cambie el operador = a IN.
•El operador NOT se puede utilizar con los operadores IN, ANY y ALL.
•Utilizan operadores de comparación de varias filas:
Operador | Significado |
IN | Igual que algún miembro de la lista |
ANY | Compara el valor con cada valor devuelto por la subconsulta |
ALL | Compara el valor con todos los valores devueltos por la subconsulta |
Ejemplos:
SELECT last_name, salary, department_id
FROM employees
WHERE salary IN (SELECT MIN(salary)
FROM employees
GROUP BY department_id);
/*El anterior ejemplo muestra los empleados que tienen una salario igual al salario mínimo de algún departamento. La consulta interna retorna una lista de salario correspondientes a los salarios mínimos por departamentos, luego en la consulta principal se compara los salarios de cada empleado con los valores retornados por la consulta interior.*/
---
Operador ANY:
El operador ANY (y su sinónimo, el operador SOME) compara un valor con cada valor devuelto por la subconsulta.
---
>ALL significa más que el máximo y <ALL, menos que el mínimo.
---
El motivo es que todas las condiciones que comparan un valor nulo dan como resultado un valor nulo. Así pues, siempre que sea probable que en el juego de resultados de una subconsulta haya valores nulos, no utilice el operador NOT IN. El operador NOT IN es equivalente a <> ALL.
SELECT employee_id, last_name, job_id, salary
FROM employees
WHERE salary < ANY
(SELECT salary
FROM employees
WHERE job_id = 'IT_PROG')
AND job_id <> 'IT_PROG';
/*Este ejemplo muestra empleados que no son programadores informáticos y cuyo salario es menor que el de cualquier programador informático.*/
---
Operador ALL:
El operador ALL compara un valor con todos los valores devueltos por una subconsulta.>ALL significa más que el máximo y <ALL, menos que el mínimo.
---
SELECT employee_id, last_name, job_id, salary
FROM employees
WHERE salary > ALL
(SELECT salary
FROM employees
WHERE job_id = 'IT_PROG')
AND job_id != 'IT_PROG';
/*Este ejemplo muestra empleados que no son programadores informáticos y cuyo salario es mayor que el de todos los programadores informáticos.*/
---
_____________________________________________________________________________________
Valores Nulos en SubConsultas.
Un problema habitual de las subconsultas de una o varias filas, se produce cuando la consulta interna no devuelve ninguna fila. Como la subconsulta no genera ninguna fila, dicha consulta retorna NULL y cualquier comparación con NULL retorna NULL, por lo cual el Query completo no retorna ninguna fila:
NULL = NULL : NULL
NULL < NULL : NULL
NULL > NULL : NULL
NULL != NULL : NULL
Otro caso es cuando se usa el operador NOT IN en subconsultas de varias filas y dicha subconsulta retorna por los menos un valor NULL. Al darse este caso la consulta principal no retorna ningún resultado.
Ejemplos:
SELECT *
SELECT *
FROM employees
WHERE department_id =
(SELECT department_id
FROM employees
WHERE last_name = 'Gambito');
/*El Query anterior trata de mostrar los empleados que sean de mismo departamento del empleado 'Gambito', pero como no hay empleados con ese apellido, la subconsulta retorna NULL, y aunque haya empleados con el campo department_id NULL, NULL no es igual a NULL por lo cual no se muestran resultados en todo el Query.*/
---
SELECT emp.last_name
FROM employees emp
WHERE emp.employee_id NOT IN
(SELECT mgr.manager_id
FROM employees mgr);
/*La sentencia SQL anterior intenta mostrar todos los empleados que no tienen subordinados. Por lógica,
esta sentencia SQL debería haber devuelto algunas filas. Sin embargo, la sentencia
SQL no devuelve ninguna fila ya que uno de los valores devueltos por la consulta
interna es un valor nulo y por eso la consulta entera no devuelve ninguna fila.
Recuerda que 'NOT IN' es igual a '!= ALL'*/
---
SELECT emp.last_name
FROM employees emp
FROM employees emp
WHERE emp.employee_id IN
(SELECT mgr.manager_id
FROM employees mgr);
/*Este Query muestra los empleados que son supervisores, notamos que aunque haya empleados con el campo manager_id NULL, el Query retorna resultados ya que el operador 'IN' es equivalente a '=ANY'.*/
Nota: De forma alternativa, se puede incluir una cláusula WHERE en la subconsulta para mostrar todos los empleados que no son supervisores:
SELECT last_name
FROM employees
WHERE employee_id NOT IN
(SELECT manager_id
FROM employees
WHERE manager_id IS NOT NULL);
_____________________________________________________________________________________
_____________________________________________________________________________________