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 SELECT que participen en el UNION tienen 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: FLOAT e INT

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.