Cons SQL
Cons SQL
Cons SQL
or ejemplo, para ordenar los resultados de forma ascendente por ciudad, y los que
sean de la misma ciudad de forma descendente por nombre, utilizaríamos esta
cláusula de ordenación:
… ORDER BY Ciudad, Nombre DESC …
Algunos ejemplos
Para terminar este repaso a las consultas simples practicarlas un poco, veamos
algunos ejemplos con la base de datos Northwind en SQL Server:
- Mostrar los clientes que no sabemos a qué región pertenecen (o sea, que no
tienen asociada ninguna región) :
SELECT * FROM Customers WHERE Region IS NULL
- Mostrar las distintas regiones de las que tenemos algún cliente, accediendo sólo a
la tabla de clientes:
SELECT DISTINCT Region FROM Customers WHERE Region IS NOT NULL
- Mostrar los clientes que pertenecen a las regiones CA, MT o WA, ordenados por
región ascendentemente y por nombre descendentemente.
CODE SELECT * FROM Customers WHERE Region IN(‘CA’, ‘MT’, ‘WA’)
- Mostrar las Ventas del producto 65 con cantidades entre 5 y 10, o que no tengan
descuento:
SELECT * FROM [Order Details] WHERE (ProductID = 65 AND Quantity BETWEEN
5 AND 10) OR Discount = 0
Para obtener datos se utiliza el comando SELECT. El formato es el siguiente:
Es importante hacer notar que cada comando SQL finaliza con punto y coma(;). Cuando se
escriben scripts, estos utilizarán un slash (/) al final del comando.
FROM
Especifica la tabla o lista de tablas de las que se recuperarán los datos. Por ejemplo para obtener
los datos del nombre y departamento de los empleados de la empresa, se puede utilizar la
siguiente consulta:
WHERE
Este permite filtrar las filas seleccionadas, por medio de una condición, que define el criterio de
selección. El formato de la condición es la mayoría de los casos: expresión operador expresión.
Las expresiones pueden ser constantes, operaciones aritméticas, valores nulos o el nombre de una
columna. Mientras que los operadores de comparación son los siguientes:
Operadores Comparación
=, >, <, >=, <=, !=, <>
IN, NOT IN, BETWEEN, NOT
BETWEEN
LIKE
IS NULL, IS NOT NULL
Se pueden construir condiciones múltiples basados en los operadores lógicos AND, OR y NOT.
También se pueden utilizar los paréntesis para establecer el orden de precedencia. Algunos
ejemplos de cláusulas WHERE son:
SELECT *
FROM dept
ORDER BY dname
Se pueden situar varios criterios, siendo la precedencia de izquierda a derecha.
ALL
Esta es la opción para recuperar todas las filas de la consulta, aunque se encuentre repetidas. Es
la opción por defecto.
DISTINCT
Sólo recupera las filas que son distintas. Si se consultamos los departamentos de la tabla de
empleados, el resultado serían los números de departamento de existentes:
SELECT deptno
FROM emp
En este caso aparecen todos los departamentos de los empleados, aunque el número de
departamento se repita entre filas. Para eliminar los repetidos se puede hacer de la siguiente
forma:
En el caso del WHERE se utiliza para crear el criterio de selección del grupo y hacer las uniones
entre tablas.
Por ejemplo:
Operadores de Comparación
Función
Operador
= Igual a
> Mayor que
>= Mayor o igual que
< Menor que
<= Menor o igual que
!= <> Distinto de
Operadores Lógicos
Operador Función
AND TRUE si ambas condiciones son TRUE
TRUE si una de ambas condiciones es
OR
TRUE
TRUE si la condición es FALSE y FALSE
NOT
si la condición es TRUE.
SELECT *
FROM emp
WHERE job = 'MANAGER'
Sin embargo, este operador no nos sirve si lo que deseamos es listar los empleados cuyo nombre
inicie con la letra 'E', en cuyo caso podemos utilizar el operador LIKE, el cual permite incluir los
siguientes caracteres especiales:
SELECT *
FROM emp
WHERE ename LIKE 'E%'
Comprobaciones con conjuntos
Tenemos, además de las operaciones binarias ya vistas, otras que comparar los datos contra una
lista.
De esta forma el IN se puede utilizar para verificar si una expresión pertenece o no a un conjunto
de valores. Su forma general es
SELECT *
FROM emp
WHERE deptno IN ( 10, 20 );
SELECT ename
FROM emp
WHERE job IN ( 'CLERK', 'SALESMAN' )
Otra opción puede ser el verificar si una expresión se encuentra o no en un rango específico, esto
por medio del BETWEEN, cuyo formato es:
Ejemplo de su utilización:
SELECT AVG(sal)
FROM emp
A pesar de que aquí la totalidad de los empleados se manejan como un grupo, puede ser
necesario trabajar sobre grupos más pequeños o determinados. Este podría ser el caso que querer
tener el salario promedio por departamento:
El uso de having sirve para expresar condiciones sobre las agrupaciones, de tal forma que
podemos escoger que grupos se despliegan. De esta forma podemos limitar la consulta ya vista
solo para los departamentos que tengan más de 3 empleados:
Por ejemplo existen vistas que indican el nombre de las tablas, en este caso la vista dictionary nos
muestra las tablas de la base de datos junto con sus comentarios.
SELECT table_name
FROM dictionary
ORDER BY table_name;
Otras tablas interesantes son all_tables, all_columns, all_views y all_constraints.
Para visualizar el nombre de las columnas que componen una tabla se utiliza la instrucción "DESC
nombre_tabla". El DESC viene de DESCribe, en este caso la abreviación es la más utilizada.
Otra vista muy utilizada es el cat, que muestra los objetos como tablas, secuencias y vistas propios
del usuario que está conectado.
SELECT d.dname,
e.ename,
e.hiredate
FROM emp e, dept d
WHERE d.deptno = e.deptno
ORDER BY d.dname,e.ename;
Ahora agregamos el nombre del jefe del empleado a la misma consulta.
SELECT d.dname,
e.ename,
e.hiredate,
m.dname manager
FROM emp e, emp m, dept d
WHERE d.deptno = e.deptno
AND m.empno = e.mgr
ORDER BY d.dname,e.ename;
En este caso para la salida se utilizó un alias para el nombre jefe "manager".
SELECT X.dname,
Z.ename
FROM emp Z,
dept X
ORDER BY X.dname, Z.ename;
En este caso si emp tiene 10 empleado y departamento 3 departamentos, la consulta retornará 30
filas. Esto es por cada nombre departamento se listan todos los empleados sin importar el
departamento. Es entonces necesario para agregar la cláusula WHERE X.deptno = Z.deptno, para
que el resultado sea el deseado, o sea 10 filas.
Outer Joins
Cuando se habla de utilizar outer join, quiere decir que se pueden seleccionar filas de una tabla
aunque no existan correspondientes en la otra tabla. Para ello se utiliza el símbolo (+):
SELECT d.dname,
e.ename
FROM emp e,
dept d,
WHERE d.deptno(+) = e.deptno
ORDER BY d.dname,e.ename
En un caso hipotético, el presidente de la compañía nunca fue asignado a un departamento, por
que nunca hubiese sido obtenido en las consultas anteriores, dado que el número de departamento
está nulo. El outer join hace que todos los registros de la tabla de empleados sean obtenidos, por
lo cual las columnas de la tabla de departamentos quedan vacías (en este caso el nombre del
departamento).
Subconsultas (subqueries)
Las subconsultas o consultas anidadas (nested), son utilizadas partiendo de una liga con la
consulta padre. Dependiendo como se cree la subconsulta, ella puede ser una vez para consulta
padre o bien una vez para cada registro retornado por la consulta padre, en este caso esta es
una consulta correlacionada.
SELECT e.ename,
e.job
FROM emp e
WHERE e.deptno IN (SELECT deptno
FROM dept
WHERE dname = 'ADMIN');
El anterior es un ejemplo de una consulta no correlacionada. En este caso se buscan los
empleados que estén en departamento ADMIN. El uso del IN es para indicar si está contenido
(puede combinarse con el NOT), y es utilizado cuando la subconsulta devuelve cero, uno o más
registros. Si se utilizará el operador de igualdad (=), se asume que solo una fila es retornada. Si la
subconsulta no devuelve ninguna columna o más de una se daría un error Oracle.
Además véase que consulta podría escribirse directamente con un join. Por lo que las
subconsultas son utilizadas generalmente por criterios de rendimiento o porque los joins no dan la
posibilidad de construir la consulta.
SELECT d.dname,
e.ename,
e.job
FROM emp e,
dept d
WHERE e.deptno = d.deptno
AND e.empno IN (SELECT repid
FROM customer
WHERE repid = e.empno)
ORDER BY d.dname, e.ename
En este caso solo los empleados que tengan al menos un cliente son tomados en cuenta. Véase
que esta es una subconsulta correlacionada, pues referencia a una columna de la consulta padre
dentro de ella.
SELECT d.dname,
e.ename,
e.job
FROM emp e,
dept d
WHERE e.deptno = d.deptno
AND NOT EXISTS (SELECT 'X'
FROM customer
WHERE city in ('ROCHESTER','NEW YORK')
AND repid = e.empno)
ORDER BY d.dname, e.job, e.ename;
En este caso se muestran todos los empleados y departamentos, excepto aquellos departamentos
que tengan clientes que se ubiquen en 'ROCHESTER' y 'NEW YORK'. SELECT 'X' será retornado
y para evaluado por el NOT EXISTS (cuando no encuentre filas en la subconsulta es falso y
cuando encuentra al menos uno es verdadero).
Puede utilizar cualquier constante en lugar de la 'X' o bien un campo de las tablas de la
subconsulta (es mejor la constante).
SELECT SUBSTR(address,1,20),
city
FROM customer
WHERE address IS NOT NULL
AND UPPER(city) = 'ROCHESTER'
Véase que UPPER hacer que al convertir a mayúscula el nombre de la ciudad, hará que si
'Rochester' aparece se convierta para luego compararse con 'ROCHESTER', de tal forma que sean
iguales.
SELECT e.ename,
e.job,
DECODE(e.job, 'President', '******', e.sal)
FROM emp e
WHERE e.empno IN (SELECT NVL(z.mgr, e.empno)
FROM emp z);
En esta consulta todos los nombres de los jefes serán obtenidos junto con su salario. Cuando la fila
del presidente es obtenida se presentará '******' en lugar de su salario.
Véase que con la función NVL para evaluar el manager_id. En este caso solo el presidente tiene el
manager_id nulo y por tanto no será obtenido sin el NVL.
Aunque sal es de distinto tipo de '******', no da error pues Oracle hacer la conversión automática de
sal a carácter.
SELECT e.ename,
e.job,
e.sal
FROM emp e
WHERE DECODE(USER,'PRES',e.empno, UPPER(e.ename),e.empno, 0) = e.empno;
En este caso, si el usuario es el presidente todos los empleados serán obtenidos, con los demás
empleados solo se obtiene el correspondiente salario.
SELECT e.ename,
e.job
DECODE(USER,'ADMIN', DECODE(e.job, 'PRESIDENT', '*****', e.sal),
'PRES', e.sal, '******')
FROM emp e
WHERE e.empno in (SELECT NVL(z.mgr, e.empno)
FROM emp z);
Acá se utiliza un DECODE anidado dentro de otro. Si el usuario Oracle es 'ADMIN' se muestra el
salario de todos excepto del presidente, si el usuario es el presidente presenta todos los salarios y
para cualquier otro solo asteriscos.
SELECT d.dname,
e.job,
e.ename
FROM emp e,
dept d
WHERE d.deptno = e.deptno
ORDER BY DECODE(e.job,'PRESIDENT', 0,
DECODE(d.dname,'SALES', 1, 'ADMIN', 2, 3)),
e.ename;
En este caso se utiliza el ORDER BY para ordenar según el job, pero se ajusta para que aparezca
primero el presidente luego los vendedores, administradores y todos los demás. Luego del decode
son ordenados por el ename.
SELECT FIRST_NAME,SALARY
FROM employees
where salary > (SELECT salary
from employees
where employee_id = 103);
SELECT FIRST_NAME,SALARY
FROM employees
where salary > (SELECT salary
from employees
where employee_id = 103)
and hire_date < (SELECT hire_date
from employees
where employee_id= 103);
--funcioens de grupo
SELECT FIRST_NAME,SALARY
FROM employees
where salary > (SELECT ROUND(AVG(salary)) FROM employees);
--CON HAVING
select *from employees;
SELECT CEIL(AVG(salary)
from employees