Sentencia UNION en SQL
UNION es una instrucción u operador que permite unir 2 o más SELECT concatenando los resultados de ejecución en un único conjunto de resultados. A diferencia de la cláusula JOIN, que agrega al conjunto de resultados las columnas específicas de cada tabla, UNION no crea registros individuales a partir de las columnas de las tablas que participan en la unión, sino que concatena el conjunto de resultados de las mismas.
Este funcionamiento esta supeditado a unas reglas estrictas que no pueden ser violadas:
- Las
SELECTque participen en elUNIONtienen que constar del mismo número de columnas. - Las columnas tienen que estar emparejadas en orden, siendo del mismo tipo de dato o en su defecto, datos compatibles, por ejemplo:
FLOATeINT…
Las reglas anteriores ponen de manifiesto que en muchas ocasiones UNION se utiliza para concatenar tablas espejos o muy similares en su definición, que aunque guarden distinta información, comparten un modelo de datos semejante.
Habrá que tener en cuenta que el nombre de las columnas del conjunto de resultados, estará definido por las columnas de la primera sentencia SELECT, por lo que en ocasiones puede ser recomendable poner un alias a alguna columna cuyo dato que almacene pueda ser sustancialmente diferente respecto a la información recogidas de una tabla a otra.
Así mismo, debemos tener en cuenta que UNION excluye valores duplicados. Si queremos que nuestro conjunto de resultados incluya duplicados, debemos sustituir el operador UNION por UNION ALL.
Para ejemplificar de manera coherente el funcionamiento de esta instrucción, vamos a crear primero una nueva tabla Empleados que se ajuste al modelo de la tabla Clientes, para posteriormente realizar un UNION de ambas.
Con el fin de que el usuario pueda replicar en su base de datos estos mismos ejemplos, dejamos los scripts del CREATE TABLE y los INSERT INTO de los datos de la nueva tabla.
CREATE TABLE Empleados(
idEmpleado INT IDENTITY(1,1),
nombre VARCHAR(255) NOT NULL ,
apellidos VARCHAR(255) NOT NULL ,
direccion VARCHAR(255),
numeroEmpleado INT
CONSTRAINT pk_Empleados_idEmpleado PRIMARY KEY (idEmpleado)
);
INSERT INTO Empleados
(nombre,
apellidos,
direccion,
numeroEmpleado)
VALUES
('Jesús',
'Hidalgo Galvez',
'C/ Conde Peñalver 24',
1001);
INSERT INTO Empleados
(nombre,
apellidos,
direccion,
numeroEmpleado)
VALUES
('Antonio',
'Silva García',
'C/ Aranda 1',
1002);
Una vez creada e introducido datos en la nueva tabla Empleados, pasamos a ejemplificar el uso del operador UNION:
SELECT nombre,
apellidos,
direccion,
cuenta as CuentaClienteNumeroEmpleado
FROM Clientes
WHERE cuenta IS NOT NULL
UNION
SELECT nombre,
apellidos,
direccion,
numeroEmpleado
FROM Empleados
ORDER BY CuentaClienteNumeroEmpleado ASC;
| nombre | apellidos | direccion | CuentaClienteNumeroEmpleado |
|---|---|---|---|
| Jesús | Hidalgo Galvez | C/ Conde Peñalver 24 | 1001 |
| Antonio | Silva García | C/ Aranda 1 | 1002 |
| Fernando | García Rodriguez | C/ Virgen del rosal 28 | 111222333 |
| María | Lopez ruiz | C/ Alcalá 138 | 123456789 |
| Ana | Fernandez Montero | Av. de Santiago 11 | 998344567 |
| Luis | Sanchez García | C/ de la luz 21 | 447824556 |
| Alejandro | Valero Martinez | C/ Serrano 67 | 778345112 |
| Paloma | Sanz Valdivia | Av. de la Ilustración 49 | 790763467 |
| Ana | Fernandez Montero | Av. de Santiago 11 | 998344567 |
Observamos que en un único conjunto de resultados estamos devolviendo los registros de la tabla Clientes y Empleados.
Como ya indicamos anteriormente, al no ser un JOIN, no podemos tener columnas independientes para guardar los valores del campo cuenta de la tabla Clientes, y el campo numeroEmpleado de la tabla Empleados, teniendo que guardarse todos los valores en la misma columna. En su defecto hemos creado un alias: CuentaClienteNumeroEmpleado, para especificar que dicha columna puede guardar ambos valores, y dada su naturaleza, diferenciar cuales pertenecen a un cliente y cuales a un empleado.
Existen otros operadores de conjuntos como el EXCEPT e INTERSECT que explicaremos a continuación utilizando como ejemplo la tabla Clientes:
INTERSECT
INTERSECT devuelve únicamente los registros comunes a la unión de todas las consultas:
SELECT idClientes,
nombre,
apellidos,
direccion,
cuenta
FROM Clientes
WHERE idClientes IN (1,2,3,4)
INTERSECT
SELECT idClientes,
nombre,
apellidos,
direccion,
cuenta
FROM Clientes
WHERE idClientes IN (4,5,6,7);
| idClientes | nombre | apellidos | direccion | cuenta |
|---|---|---|---|---|
| 4 | Luis | Sanchez García | C/ de la luz 21 | 447824556 |
En este caso, podemos observar que solo el registro con idClientes = 4, es devuelto comúnmente por ambas consultas.
EXCEPT
EXCEPT devuelve únicamente los registros exclusivos de la primera consulta, no coincidentes con el resto:
SELECT idClientes,
nombre,
apellidos,
direccion,
cuenta
FROM Clientes
WHERE idClientes IN (1,2,3,4)
EXCEPT
SELECT idClientes,
nombre,
apellidos,
direccion,
cuenta
FROM Clientes
WHERE idClientes IN (4,5,6,7);
| idClientes | nombre | apellidos | direccion | cuenta |
|---|---|---|---|---|
| 1 | Fernando | García Rodriguez | C/ Virgen del rosal 28 | 111222333 |
| 2 | María | Lopez ruiz | C/ Alcalá 138 | 123456789 |
| 3 | Ana | Fernandez Montero | Av. de Santiago 11 | 998344567 |
En este caso, solo los idClientes 1,2,3, son devueltos exclusivamente por la primera consulta de la unión.