En MySQL, la UNION
La cláusula combina los resultados de varias consultas en un único conjunto de resultados.
Ejemplo
Supongamos que tenemos las siguientes tablas:
SELECT * FROM Teachers;
SELECT * FROM Students;
Resultado:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 1 | Warren | | 2 | Ben | | 3 | Cathy | | 4 | Cathy | | 5 | Bill | | 6 | Bill | +-----------+-------------+ +-----------+-------------+ | StudentId | StudentName | +-----------+-------------+ | 1 | Faye | | 2 | Jet | | 3 | Spike | | 4 | Ein | | 5 | Warren | | 6 | Bill | +-----------+-------------+
Podemos insertar el UNION
cláusula entre esos dos SELECT
declaraciones para devolver a todos los profesores y estudiantes:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentName FROM Students;
Resultado:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Bill | | Faye | | Jet | | Spike | | Ein | +-------------+
Los nombres de las columnas se toman del primer SELECT
declaración.
De forma predeterminada, UNION
cláusula aplica implícitamente un DISTINCT
operación. En otras palabras, devuelve solo valores distintos de forma predeterminada. Entonces, los resultados anteriores contienen solo uno de Warren, Cathy y Bill. Esto es a pesar del hecho de que las tablas combinadas en realidad contienen dos Warren, dos Cathy y tres Bill (hay dos maestros llamados Cathy, un maestro y un cliente llamado Warren, y dos llamados Bill, así como un estudiante llamado Bill).
Aquí hay un ejemplo que usa explícitamente DISTINCT
cláusula:
SELECT TeacherName FROM Teachers
UNION DISTINCT
SELECT StudentName FROM Students;
Resultado:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Bill | | Faye | | Jet | | Spike | | Ein | +-------------+
Entonces obtenemos el mismo resultado que obtuvimos sin DISTINCT
cláusula.
Incluir duplicados
Podemos usar el ALL
palabra clave para incluir valores duplicados en los resultados:
SELECT TeacherName FROM Teachers
UNION ALL
SELECT StudentName FROM Students;
Resultado:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Cathy | | Bill | | Bill | | Faye | | Jet | | Spike | | Ein | | Warren | | Bill | +-------------+
Esta vez obtuvimos doce filas en lugar de las ocho que obtuvimos en nuestro primer ejemplo.
Podemos ver que ambos Cathys fueron devueltos y los tres Bills fueron devueltos.
TABLE
Declaraciones
Desde MySQL 8.0.19 podemos usar UNION
cláusula con la TABLE
declaración.
He aquí un ejemplo:
TABLE Teachers
UNION
TABLE Students;
Resultado:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 1 | Warren | | 2 | Ben | | 3 | Cathy | | 4 | Cathy | | 5 | Bill | | 6 | Bill | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 4 | Ein | | 5 | Warren | +-----------+-------------+
Ese es el equivalente de la siguiente consulta:
SELECT * FROM Teachers
UNION
SELECT * FROM Students;
Resultado:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 1 | Warren | | 2 | Ben | | 3 | Cathy | | 4 | Cathy | | 5 | Bill | | 6 | Bill | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 4 | Ein | | 5 | Warren | +-----------+-------------+
Notará que estas declaraciones devuelven más filas que en nuestro primer ejemplo anterior. Esto se debe a que estamos seleccionando todas las columnas de la tabla, lo que da como resultado que no haya duplicados donde antes había un duplicado. Por ejemplo, aquí se devuelven dos profesores llamados Bill, mientras que en el ejemplo anterior solo se devolvía uno. Eso es porque el TeacherId
las columnas contienen valores diferentes, por lo que las filas no están duplicadas.
Usando ORDER BY
Cláusula en consultas de unión
Podemos usar el ORDER BY
cláusula en cada SELECT
declaración y/o en la UNION
combinada consulta.
En cada SELECT
Declaración
Cuando usamos el ORDER BY
cláusula en el SELECT
individual declaraciones dentro de un UNION
consulta, necesitamos incluir cada SELECT
declaración entre paréntesis:
(SELECT * FROM Teachers ORDER BY TeacherName ASC LIMIT 2)
UNION
(SELECT * FROM Students ORDER BY StudentName ASC LIMIT 2);
Resultado:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 2 | Ben | | 5 | Bill | | 6 | Bill | | 4 | Ein | +-----------+-------------+
Tenga en cuenta que cuando hacemos esto, en realidad no ordena los resultados para la salida. Solo ordena los resultados con el fin de determinar el subconjunto de las filas seleccionadas para recuperar al aplicar el LIMIT
cláusula.
Por lo tanto, usando ORDER BY
sin el LIMIT
cláusula no tiene efecto en la salida.
En conjunto UNION
Consulta
También podemos usar un ORDER BY
cláusula en toda la consulta, de modo que toda la salida se ordene en conjunto.
En este ejemplo, tomamos el ejemplo anterior y ordenamos los resultados combinados:
(SELECT * FROM Teachers ORDER BY TeacherName ASC LIMIT 2)
UNION
(SELECT * FROM Students ORDER BY StudentName ASC LIMIT 2)
ORDER BY TeacherName DESC;
Resultado:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 4 | Ein | | 5 | Bill | | 6 | Bill | | 2 | Ben | +-----------+-------------+
Incluso cuando no se utiliza el ORDER BY
cláusula dentro de cada SELECT
declaración, cada SELECT
declaración aún debe estar entre paréntesis, y el ORDER BY
cláusula (o cualquier LIMIT
cláusula) debe ir después de la última.
(SELECT * FROM Teachers)
UNION
(SELECT * FROM Students)
ORDER BY TeacherName ASC;
Resultado:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 2 | Ben | | 5 | Bill | | 6 | Bill | | 3 | Cathy | | 4 | Cathy | | 4 | Ein | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 1 | Warren | | 5 | Warren | +-----------+-------------+
Eso sí, omitir los paréntesis produce el mismo resultado que el que tiene paréntesis:
SELECT * FROM Teachers
UNION
SELECT * FROM Students
ORDER BY TeacherName ASC;
Resultado:
+-----------+-------------+ | TeacherId | TeacherName | +-----------+-------------+ | 2 | Ben | | 5 | Bill | | 6 | Bill | | 3 | Cathy | | 4 | Cathy | | 4 | Ein | | 1 | Faye | | 2 | Jet | | 3 | Spike | | 1 | Warren | | 5 | Warren | +-----------+-------------+
Tenga en cuenta que si una columna que se ordenará usa un alias, esa columna debe ser referenciada por su alias (no por el nombre de la columna).
Ejemplo:
(SELECT TeacherName t FROM Teachers)
UNION
(SELECT StudentName FROM Students)
ORDER BY t ASC;
Resultado:
+--------+ | t | +--------+ | Ben | | Bill | | Cathy | | Ein | | Faye | | Jet | | Spike | | Warren | +--------+
Esto es lo que sucede si no usamos el alias:
(SELECT TeacherName t FROM Teachers)
UNION
(SELECT StudentName FROM Students)
ORDER BY TeacherName ASC;
Resultado:
ERROR 1054 (42S22): Unknown column 'TeacherName' in 'order clause'
Número de columnas
El número de columnas devueltas por cada SELECT
declaración debe ser la misma. Por lo tanto, no podemos hacer lo siguiente:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentId, StudentName FROM Students;
Resultado:
ERROR 1222 (21000): The used SELECT statements have a different number of columns
Tipos de datos
Columnas seleccionadas enumeradas en las posiciones correspondientes de cada SELECT
declaración debe tener el mismo tipo de datos. Sin embargo, si no lo hacen, los tipos y longitudes de las columnas en UNION
resultado tenga en cuenta los valores recuperados por todos los SELECT
declaraciones.
Esto es lo que sucede si intentamos combinar el TeacherName
columna con el StudentId
columna:
SELECT TeacherName FROM Teachers
UNION
SELECT StudentId FROM Students;
Resultado:
+-------------+ | TeacherName | +-------------+ | Warren | | Ben | | Cathy | | Bill | | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | +-------------+
Algunos otros RDBMS producirían un error en este caso, pero MySQL logra generar resultados sin errores.