#### 13.2.10.3 UNION Clause

[]()

```
SELECT ...
UNION [ALL | DISTINCT] SELECT ...
[UNION [ALL | DISTINCT] SELECT ...]
```

[`UNION`](union.html) combines the result from multiple [`SELECT`](select.html) statements into a single result set. Example:

```
mysql> SELECT 1, 2;
+---+---+
| 1 | 2 |
+---+---+
| 1 | 2 |
+---+---+
mysql> SELECT 'a', 'b';
+---+---+
| a | b |
+---+---+
| a | b |
+---+---+
mysql> SELECT 1, 2 UNION SELECT 'a', 'b';
+---+---+
| 1 | 2 |
+---+---+
| 1 | 2 |
| a | b |
+---+---+
```

* [Result Set Column Names and Data Types](union.html#union-result-set)

* [TABLE in Unions](union.html#union-table)

* [UNION DISTINCT and UNION ALL](union.html#union-distinct-all)

* [ORDER BY and LIMIT in Unions](union.html#union-order-by-limit)

* [UNION Restrictions](union.html#union-restrictions)

* [UNION Handing in MySQL 8.0 Compared to MySQL 5.7](union.html#union-8-0-versus-5-7)

##### Result Set Column Names and Data Types

 The column names for a [`UNION`](union.html) result set are taken from the column names of the first [`SELECT`](select.html) statement.

 Selected columns listed in corresponding positions of each [`SELECT`](select.html) statement should have the same data type. For example, the first column selected by the first statement should have the same type as the first column selected by the other statements. If the data types of corresponding [`SELECT`](select.html) columns do not match, the types and lengths of the columns in the [`UNION`](union.html) result take into account the values retrieved by all the [`SELECT`](select.html) statements. For example, consider the following, where the column length is not constrained to the length of the value from the first [`SELECT`](select.html):

```
mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',20);
+----------------------+
| REPEAT('a',1)        |
+----------------------+
| a                    |
| bbbbbbbbbbbbbbbbbbbb |
+----------------------+
```

##### TABLE in Unions

 Beginning with MySQL 8.0.19, you can also use a [`TABLE`](table.html) statement or [`VALUES`](values.html) statement in a [`UNION`](union.html) wherever you can employ the equivalent [`SELECT`](select.html) statement. Assume that tables `t1` and `t2` are created and populated as shown here:

```
CREATE TABLE t1 (x INT, y INT);
INSERT INTO t1 VALUES ROW(4,-2),ROW(5,9);

CREATE TABLE t2 (a INT, b INT);
INSERT INTO t2 VALUES ROW(1,2),ROW(3,4);
```

 The preceding being the case, and disregarding the column names in the output of the queries beginning with [`VALUES`](values.html), all of the following `UNION` queries yield the same result:

```
SELECT * FROM t1 UNION SELECT * FROM t2;
TABLE t1 UNION SELECT * FROM t2;
VALUES ROW(4,-2), ROW(5,9) UNION SELECT * FROM t2;
SELECT * FROM t1 UNION TABLE t2;
TABLE t1 UNION TABLE t2;
VALUES ROW(4,-2), ROW(5,9) UNION TABLE t2;
SELECT * FROM t1 UNION VALUES ROW(4,-2),ROW(5,9);
TABLE t1 UNION VALUES ROW(4,-2),ROW(5,9);
VALUES ROW(4,-2), ROW(5,9) UNION VALUES ROW(4,-2),ROW(5,9);
```

 To force the column names to be the same, wrap the [`VALUES`](values.html) on the left hand side in a `SELECT` and use aliases, like this:

```
SELECT * FROM (VALUES ROW(4,-2), ROW(5,9)) AS t(x,y)
  UNION TABLE t2;
SELECT * FROM (VALUES ROW(4,-2), ROW(5,9)) AS t(x,y)
  UNION VALUES ROW(4,-2),ROW(5,9);
```

##### UNION DISTINCT and UNION ALL

 By default, duplicate rows are removed from [`UNION`](union.html) results. The optional `DISTINCT` keyword has the same effect but makes it explicit. With the optional `ALL` keyword, duplicate-row removal does not occur and the result includes all matching rows from all the [`SELECT`](select.html) statements.

 You can mix [`UNION ALL`](union.html) and [`UNION DISTINCT`](union.html) in the same query. Mixed [`UNION`](union.html) types are treated such that a `DISTINCT` union overrides any `ALL` union to its left. A `DISTINCT` union can be produced explicitly by using [`UNION DISTINCT`](union.html) or implicitly by using [`UNION`](union.html) with no following `DISTINCT` or `ALL` keyword.

 In MySQL 8.0.19 and later, `UNION ALL` and `UNION DISTINCT` work the same way when one or more [`TABLE`](table.html) statements are used in the union.

##### ORDER BY and LIMIT in Unions

 To apply an `ORDER BY` or `LIMIT` clause to an individual [`SELECT`](select.html), parenthesize the [`SELECT`](select.html) and place the clause inside the parentheses:

```
(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);
```

 Use of `ORDER BY` for individual [`SELECT`](select.html) statements implies nothing about the order in which the rows appear in the final result because [`UNION`](union.html) by default produces an unordered set of rows. Therefore, `ORDER BY` in this context typically is used in conjunction with `LIMIT`, to determine the subset of the selected rows to retrieve for the [`SELECT`](select.html), even though it does not necessarily affect the order of those rows in the final [`UNION`](union.html) result. If `ORDER BY` appears without `LIMIT` in a [`SELECT`](select.html), it is optimized away because it has no effect in any case.

 To use an `ORDER BY` or `LIMIT` clause to sort or limit the entire [`UNION`](union.html) result, parenthesize the individual [`SELECT`](select.html) statements and place the `ORDER BY` or `LIMIT` after the last one:

```
(SELECT a FROM t1 WHERE a=10 AND B=1)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2)
ORDER BY a LIMIT 10;
```

 A statement without parentheses is equivalent to one parenthesized as just shown.

 Beginning with MySQL 8.0.19, you can use `ORDER BY` and `LIMIT` with [`TABLE`](table.html) in unions in the same way as just shown, bearing in mind that `TABLE` does not support a `WHERE` clause.

 This kind of `ORDER BY` cannot use column references that include a table name (that is, names in *`tbl_name`*.*`col_name`* format). Instead, provide a column alias in the first [`SELECT`](select.html) statement and refer to the alias in the `ORDER BY`. (Alternatively, refer to the column in the `ORDER BY` using its column position. However, use of column positions is deprecated.)

 Also, if a column to be sorted is aliased, the `ORDER BY` clause *must* refer to the alias, not the column name. The first of the following statements is permitted, but the second fails with an `Unknown column 'a' in 'order clause'` error:

```
(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY b;
(SELECT a AS b FROM t) UNION (SELECT ...) ORDER BY a;
```

 To cause rows in a [`UNION`](union.html) result to consist of the sets of rows retrieved by each [`SELECT`](select.html) one after the other, select an additional column in each [`SELECT`](select.html) to use as a sort column and add an `ORDER BY` that sorts on that column following the last [`SELECT`](select.html):

```
(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1)
UNION
(SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col;
```

 To additionally maintain sort order within individual [`SELECT`](select.html) results, add a secondary column to the `ORDER BY` clause:

```
(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1)
UNION
(SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col, col1a;
```

 Use of an additional column also enables you to determine which [`SELECT`](select.html) each row comes from. Extra columns can provide other identifying information as well, such as a string that indicates a table name.

##### UNION Restrictions

 In a [`UNION`](union.html), the [`SELECT`](select.html) statements are normal select statements, but with the following restrictions:

* `HIGH_PRIORITY` in the first [`SELECT`](select.html) has no effect. `HIGH_PRIORITY` in any subsequent [`SELECT`](select.html) produces a syntax error.

* Only the last [`SELECT`](select.html) statement can use an `INTO` clause. However, the entire [`UNION`](union.html) result is written to the `INTO` output destination.

 As of MySQL 8.0.20, these two [`UNION`](union.html) variants containing `INTO` are deprecated and you should expect support for them to be removed in a future version of MySQL:

* In the trailing query block of a query expression, use of `INTO` before `FROM` produces a warning. Example:

  ```
  ... UNION SELECT * INTO OUTFILE 'file_name' FROM table_name;
  ```

* In a parenthesized trailing block of a query expression, use of `INTO` (regardless of its position relative to `FROM`) produces a warning. Example:

  ```
  ... UNION (SELECT * INTO OUTFILE 'file_name' FROM table_name);
  ```

   Those variants are deprecated because they are confusing, as if they collect information from the named table rather than the entire query expression (the `UNION`).

[`UNION`](union.html) queries with an aggregate function in an `ORDER BY` clause are rejected with an [`ER_AGGREGATE_ORDER_FOR_UNION`](https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html#error_er_aggregate_order_for_union) error. Example:

```
SELECT 1 AS foo UNION SELECT 2 ORDER BY MAX(1);
```

##### UNION Handing in MySQL 8.0 Compared to MySQL 5.7

 In MySQL 8.0, the parser rules for [`SELECT`](select.html) and [`UNION`](union.html) were refactored to be more consistent (the same [`SELECT`](select.html) syntax applies uniformly in each such context) and reduce duplication. Compared to MySQL 5.7, several user-visible effects resulted from this work, which may require rewriting of certain statements:

* `NATURAL JOIN` permits an optional `INNER` keyword (`NATURAL INNER JOIN`), in compliance with standard SQL.

* Right-deep joins without parentheses are permitted (for example, `... JOIN ... JOIN ... ON ... ON`), in compliance with standard SQL.

* `STRAIGHT_JOIN` now permits a `USING` clause, similar to other inner joins.

* The parser accepts parentheses around query expressions. For example, `(SELECT ... UNION SELECT ...)` is permitted. See also [Section 13.2.10.4, “Parenthesized Query Expressions”](parenthesized-query-expressions.html).

* The parser better conforms to the documented permitted placement of the `SQL_CACHE` and `SQL_NO_CACHE` query modifiers.

* Left-hand nesting of unions, previously permitted only in subqueries, is now permitted in top-level statements. For example, this statement is now accepted as valid:

  ```
  (SELECT 1 UNION SELECT 1) UNION SELECT 1;
  ```

* Locking clauses (`FOR UPDATE`, `LOCK IN SHARE MODE`) are allowed only in non-`UNION` queries. This means that parentheses must be used for `SELECT` statements containing locking clauses. This statement is no longer accepted as valid:

  ```
  SELECT 1 FOR UPDATE UNION SELECT 1 FOR UPDATE;
  ```

   Instead, write the statement like this:

  ```
  (SELECT 1 FOR UPDATE) UNION (SELECT 1 FOR UPDATE);
  ```

