Páginas

martes, 7 de enero de 2014

4.9. Operadores de conjuntos


Los operadores de conjuntos del álgebra relacional son: el producto car-
tesiano, la unión, la intersección y la diferencia. El producto cartesiano se
realiza en SQL especificando en la cláusula FROM las tablas involucradas en la
operación, separadas por comas, tal y como se ha indicado anteriormente. A
continuación se muestra cómo utilizar el resto de los operadores de conjuntos
en las consultas en SQL.
La sintaxis para las uniones, intersecciones y diferencias es la siguiente:
sentencia_SELECT
UNION | INTERSECT | EXCEPT [ ALL ]
sentencia_SELECT
[ ORDER BY columna [ ASC | DESC ]
[,columna [ ASC | DESC ] ];
Nótese que la cláusula ORDER BY sólo puede aparecer una vez en la consulta,
al final de la misma. La ordenación se realizará sobre el resultado de la unión,
intersección o diferencia.
Para poder utilizar cualquiera de estos tres nuevos operadores, las cabeceras
de las sentencias SELECT involucradas deben devolver el mismo número de
columnas, y las columnas correspondientes en ambas sentencias deberán ser
del mismo tipo de datos.
83
84

4.9.1. Operador UNION

Este operador devuelve como resultado todas las filas que devuelve la pri-
mera sentencia SELECT, más aquellas filas de la segunda sentencia SELECT que
no han sido ya devueltas por la primera. En el resultado no se muestran du-
plicados.
Se puede evitar la eliminación de duplicados especificando la palabra clave
ALL. En este caso, si una fila aparece m veces en la primera sentencia y n veces
en la segunda, en el resultado aparecerá m + n veces.
Si se realizan varias uniones, éstas se evalúan de izquierda a derecha, a
menos que se utilicen paréntesis para establecer un orden distinto.
La siguiente sentencia muestra los códigos de las poblaciones donde hay
clientes o donde hay vendedores:
SELECT codpue FROM clientes
UNION
SELECT codpue FROM vendedores;

4.9.2. Operador INTERSECT

Este operador devuelve como resultado las filas que se encuentran tanto en
el resultado de la primera sentencia SELECT como en el de la segunda sentencia
SELECT. En el resultado no se muestran duplicados.
Se puede evitar la eliminación de duplicados especificando la palabra clave
ALL. En este caso, si una misma fila aparece m veces en la primera sentencia
y n veces en la segunda, en el resultado esta fila aparecerá min(m,n) veces.
Si se realizan varias intersecciones, éstas se evalúan de izquierda a derecha,
a menos que se utilicen paréntesis para establecer un orden distinto. La inter-
sección tiene más prioridad, en el orden de evaluación, que la unión, es decir,
A UNION B INTERSECT C se evalúa como A UNION (B INTERSECT C).
La siguiente sentencia muestra los códigos de las poblaciones donde hay
clientes y también hay vendedores:
SELECT codpue FROM clientes
INTERSECT
SELECT codpue FROM vendedores;
84
8?

4.9.3. Operador EXCEPT

Este operador devuelve como resultado las filas que se encuentran en el
resultado de la primera sentencia SELECT y no se encuentran en el resultado
de la segunda sentencia SELECT. En el resultado no se muestran duplicados.
Se puede evitar la eliminación de duplicados especificando la palabra clave
ALL. En este caso, si una misma fila aparece m veces en la primera sentencia y
n veces en la segunda, en el resultado esta fila aparecerá max(m−n,0) veces.
Si se realizan varias diferencias, éstas se evalúan de izquierda a derecha, a
menos que se utilicen paréntesis para establecer un orden distinto. La diferencia
tiene la misma prioridad, en el orden de evaluación, que la unión.
La siguiente sentencia muestra los códigos de las poblaciones donde hay
clientes y no hay vendedores:
SELECT codpue FROM clientes
EXCEPT
SELECT codpue FROM vendedores;
La diferencia no es una operación conmutativa, mientras que el resto de los
operadores de conjuntos sí lo son.

4.9.4. Sentencias equivalentes

En muchas ocasiones, una misma consulta de datos puede responderse me-
diante distintas sentencias SELECT que utilizan operadores diferentes. Cada
una de ellas dará, por lo general, un tiempo de respuesta diferente, y se puede
considerar que una es mejor que otra en este aspecto.
El que una sentencia sea mejor en unas circunstancias no garantiza que
vaya a serlo siempre: puede que al evolucionar el estado de la base de datos,
una sentencia que era la mejor, deje de serlo porque las tablas hayan cambiado
de tamaño o se haya creado o eliminado algún índice.
Es por todo lo anterior, que se considera importante que, ante una consulta
de datos, sea posible obtener varias sentencias alternativas. En este apartado
se presentan algunas equivalencias entre operadores que se pueden utilizar para
obtener sentencias equivalentes.
Una concatenación es equivalente a una expresión con el operador IN y
una subconsulta. Dependiendo del número de filas que obtenga la sub-
consulta, será más o menos eficiente que la concatenación con JOIN.
Una restricción con dos comparaciones unidas por OR es equivalente a la
unión de dos sentencias SELECT, y sitúa cada una de estas comparaciones
en una sentencia distinta.
Una restricción con dos comparaciones unidas por AND es equivalente
a la intersección de dos sentencias SELECT, y sitúa cada una de estas
comparaciones en una sentencia distinta.
85
86

Una restricción con dos comparaciones unidas por AND NOT es equivalente
a la diferencia de dos sentencias SELECT, y sitúa la primera comparación
en la primera sentencia y la segunda comparación en la segunda sentencia
(conviene recordar que esta operación no es conmutativa).
El operador NOT IN puede dar resultados inesperados cuando la subcon-
sulta devuelve algún nulo. En general, es más aconsejable trabajar con
operadores en positivo (sin NOT) (en el ejemplo que se ofrece después
se verá el porqué). Una restricción con el operador NOT IN y una sub-
consulta, es equivalente a una restricción con IN y una subconsulta con
EXCEPT.

4.9.5. Ejemplos

Ejemplo 4.14 Obtener los datos de las poblaciones donde hay vendedores y
no hay clientes.
SELECT *
FROM
( SELECT codpue FROM vendedores
EXCEPT
SELECT codpue FROM clientes ) AS t
JOIN pueblos USING (codpue)
JOIN provincias USING (codpro);
La tabla t contiene los códigos de las poblaciones en donde hay vendedores y
no hay clientes. Tras concatenarla con PUEBLOS y PROVINCIAS se obtienen los
datos completos de dichas poblaciones.
Ejemplo 4.15 ¿Cuántos clientes hay que entre todas sus facturas no tienen
ninguna con 18% de IVA?
La siguiente solución utiliza el operador NOT IN. Nótese que es preciso tener
en cuenta dos restricciones: la primera es que en la subconsulta del NOT IN se
debe evitar los nulos, y la segunda es que hay que asegurarse de que los clientes
seleccionados hayan realizado alguna compra (deben tener alguna factura).
SELECT COUNT(*) AS clientes
FROM
clientes
WHERE
codcli NOT IN ( SELECT codcli FROM facturas
WHERE
COALESCE(iva,0) = 18
AND
codcli IS NOT NULL )
AND
codcli IN (SELECT codcli FROM facturas);
86
87

Una sentencia equivalente sin NOT IN y que utiliza un operador de conjun-
tos, es la siguiente:
-- clientes con alguna factura
-- menos
-- clientes que tienen alguna con 18%
SELECT COUNT(*) AS clientes
FROM
( SELECT codcli FROM facturas
EXCEPT
SELECT codcli FROM facturas
WHERE
COALESCE(iva,0) = 18 ) AS t;
Trabajando con EXCEPT en lugar de NOT IN no es preciso preocuparse por los
nulos en la clave ajena FACTURAS.codcli. Otra ventaja es que no aparecen en
el resultado los clientes sin facturas. Además, suele suceder que las consultas
así formuladas consiguen mejores tiempos de respuesta que las que utilizan
NOT IN, quizá porque hay ciertas comprobaciones que se evitan.
4.10. Subconsultas correlacionadas

No hay comentarios:

Publicar un comentario