Los operadores de conjunto operan sobre dos conjuntos de
resultados de consultas, comparando filas completas entre los resultados.
Dependiendo del resultado de la comparación y del operador de conjunto
utilizado, el operador determina si retornar la fila o no. T-SQL soporta tres
operadores de conjunto: UNION, INTERSECT, y EXCEPT; también soporta un operador
multiconjunto: UNION ALL.
La forma general de código usando un operador de conjunto
es como sigue.
<consulta 1>
<operador conjunto>
<consulta 2>
[ORDER BY <lista_order_by>]
Trabajar con operadores de conjunto sigue una serie de
pautas:
·
Debido
a que las filas completas son emparejadas entre los conjuntos de resultados, el
número de columnas en las consultas tiene que ser el mismo y los tipos de
columna de las columnas correspondientes necesitan ser compatibles (convertibles
implícitamente).
·
Los
operadores de conjunto consideran dos NULLs como iguales para propósitos de
comparación. Esto es bastante inusual cuando es comparado con las cláusulas de
filtrado como WHERE y ON.
·
Debido
a que los operadores son operadores de conjunto y no operadores de cursor, a las
consultas individuales no se les permite que tengan cláusulas ORDER BY.
·
Puede
opcionalmente agregar una cláusula ORDER BY que determina el orden de
presentación del resultado del operador de conjunto.
·
Los
nombres de columna de las columnas de resultado están determinados por la
primera consulta.
UNION y UNION ALL
El operador de conjuntos UNION unifica los resultados de
las dos consultas de entrada. Como un operador de conjunto, UNION tiene una propiedad DISTINCT implícita, significando
que no retorna las filas duplicadas. La figura muestra una ilustración del
operador UNION, utilizando un diagrama de
Venn.
Como un ejemplo por utilizar el operador UNION, la
siguiente consulta retorna locaciones que son ubicaciones de empleados o
ubicaciones de clientes, o ambos.
SELECT
country, region,
city
FROM
HR.Employees
UNION
SELECT
country, region,
city
FROM
Sales.Customers;
Esta consulta genera la siguiente salida, mostrada aquí
en forma abreviada.
country region city
--------------- ---------------
---------------
UK NULL London
USA WA Kirkland
USA WA Seattle
...
(71 filas afectadas)
La tabla HR.Employees tiene 9 filas y la tabla
Sales.Customers tiene 91 filas, pero hay 71 lugares distintos en los resultados
unificados; por lo tanto, el operador UNION retorna 71 filas.
Si desea mantener los duplicados; por ejemplo, para más
adelante agrupar las filas y contar las ocurrencias, necesita utilizar el
operador multiconjunto UNION ALL en lugar de UNION. El operador UNION ALL
unifica los resultados de las dos consultas de entrada, pero no trata de
eliminar los duplicados. La figura tiene una ilustración del operador UNION ALL
utilizando un diagrama de Venn.
A modo de ejemplo, la siguiente consulta unifica
ubicaciones de empleados y ubicaciones de clientes utilizando el operador UNION
ALL.
SELECT
country, region,
city
FROM
HR.Employees
UNION ALL
SELECT
country, region,
city
FROM Sales.Customers;
Debido a que UNION ALL no intenta eliminar los duplicados,
el resultado tiene 100 filas (9 de empleados + 91 de clientes).
country region city
--------------- ---------------
---------------
USA WA Seattle
USA
WA Tacoma
USA
WA Kirkland
USA WA Redmond
UK NULL London
UK NULL London
UK NULL London
...
(100 filas afectadas)
Importante: UNION versus UNION ALL
Si los conjuntos que está unificando
son disjuntos y no hay posibilidad de duplicados, UNION y UNION ALL retornaran el
mismo resultado. Sin embargo, es importante utilizar UNION ALL en ese caso,
desde el punto de vista de rendimiento, ya que con UNION, SQL Server puede
tratar de eliminar los duplicados, incurriendo en costos innecesarios.
INTERSECT
El operador INTERSECT sólo retorna las filas distintas
que son comunes a ambos conjuntos. En otras palabras, si una fila aparece al
menos una vez en el primer conjunto y al menos una vez en el segundo conjunto,
aparecerá una vez en el resultado del operador INTERSECT. La figura ilustra el
operador INTERSECT utilizando un diagrama de Venn.
A modo de ejemplo, el código siguiente utiliza el
operador INTERSECT para retornar ubicaciones distintas que son ubicaciones de
empleados y de clientes (ubicaciones donde hay al menos un empleado y al menos
un cliente).
SELECT
country, region,
city
FROM
HR.Employees
INTERSECT
SELECT
country, region,
city
FROM
Sales.Customers;
Esta consulta genera el siguiente resultado.
country region city
--------------- ---------------
---------------
UK NULL London
USA WA Kirkland
USA WA Seattle
Observe que la ubicación (UK, NULL, London) fue retornado
porque aparece en ambos lados. Cuando compara los NULLs en la columna region en
las filas de los dos lados, el operador INTERSECT los considera como iguales. También
note que no importa cuántas veces aparece la misma ubicación en cada lado,
siempre que aparece al menos una vez en ambos lados, es retornado sólo una vez
en la salida.
EXCEPT
El operador EXCEPT realiza diferencias de conjuntos. Retorna
filas distintas que aparecen en la primera consulta, pero no la segunda. En
otras palabras, si una fila aparece al menos una vez en la primera consulta y
cero veces en la segunda, es retornado una vez en la salida. La figura ilustra
el operador EXCEPT con un diagrama de Venn.
Como ejemplo del uso de EXCEPT, la siguiente consulta retorna
las ubicaciones que son ubicaciones de empleados, pero no ubicaciones de
clientes.
SELECT
country, region,
city
FROM
HR.Employees
EXCEPT
SELECT
country, region,
city
FROM
Sales.Customers;
Esta consulta genera el siguiente resultado.
country region city
--------------- ---------------
---------------
USA WA Redmond
USA
WA Tacoma
Con UNION e INTERSECT, el orden de las consultas de
entrada no importa. Sin embargo, con EXCEPT, hay un diferente significado para
<consulta 1> EXCEPT <consulta 2> versus <consulta 2> EXCEPT
<consulta 1>.
Por último, los operadores de conjunto tienen
precedencia: INTERSECT precede a UNION y EXCEPT, y UNION y EXCEPT son
considerados iguales. Considere los siguientes operadores de conjunto.
<consulta 1> UNION <consulta 2> INTERSECT <consulta 3>;
En primer lugar, la intersección entre la consulta 2 y la
consulta 3 tiene lugar, y luego una unión entre el resultado de la intersección
y consulta 1. Siempre puede forzar la precedencia por utilizar paréntesis. Por
lo tanto, si desea que la unión tenga lugar primero, utilice la forma
siguiente.
(<consulta 1> UNION <consulta 2>) INTERSECT <consulta 3>;
Ejercicio 1: Utilice el Operador de Conjunto EXCEPT
En este ejercicio, practica la identificación de
relaciones entre clientes y empleados a través de pedidos utilizando el
operador de conjunto EXCEPT.
1. Abra el SSMS y conéctese a la base de
datos de muestra TSQL2012.
2. Escriba una consulta que retorna los
empleados que manejaron pedidos para el cliente 1, pero no para el cliente 2.
Para ello, utilice el operador de conjunto EXCEPT, de la siguiente manera.
SELECT empid
FROM Sales.Orders
WHERE custid = 1
EXCEPT
SELECT empid
FROM Sales.Orders
WHERE
custid = 2;
La primera consulta retorna los
empleados que manejan los pedidos del cliente 1, y la segunda consulta retorna
los empleados que manejan los pedidos del cliente 2. Debido a que el operador
EXCEPT es utilizado entre la primera y la segunda consulta, obtiene los
empleados que manejan los pedidos del cliente 1, pero no del 2, conforme a lo
solicitado. Recuerde que EXCEPT no retorna filas duplicadas, por lo que no necesita
preocuparse por un empleado que aparezca más de una vez en la salida. Su código
solución retorna los siguientes empleados.
empid
-----------
1
6
Ejercicio 2: Utilice el Operador de Conjunto INTERSECT
En este ejercicio, practica la identificación de las
relaciones entre los clientes y los empleados a través de pedidos utilizando el
operador de conjunto INTERSECT.
Utilizando la misma tabla Sales.Orders que utilizó en el
ejercicio 1, retorna empleados que manejaron pedidos, tanto para el cliente 1 y
para el cliente 2. Para lograr esto, utilice las mismas dos consultas de
entrada, pero esta vez intersecte los resultados utilizando el operador
INTERSECT, de la siguiente manera.
SELECT
empid
FROM
Sales.Orders
WHERE
custid = 1
INTERSECT
SELECT
empid
FROM
Sales.Orders
WHERE custid = 2;
Este código devuelve la siguiente salida.
empid
-----------
3
4
Este post trata de Combinación de Conjuntos - Usando Operadores de Conjunto. Espero les sea de utilidad.
ResponderBorrar