SELECT ... UNION子句
SELECT ...UNION [ ALL | DISTINCT ]SELECT ... [UNION [ ALL | DISTINCT ] SELECT ...]
UNION将来自多个SELECT语句的结果合并到一个结果集中。结果集列名取自第一条SELECT语句的列名。
在每个SELECT语句的相应位置列出的所选列应具有相同的数据类型。(例如,第一个语句选择的第一列应与其他语句选择的第一列具有相同的类型。)如果对应SELECT列的数据类型不匹配,则UNION结果中各列的类型和长度取考虑所有SELECT语句检索的值。例如,考虑以下内容:
mysql>SELECT REPEAT('a',1)UNION SELECT REPEAT('b',10); +--------------- + | REPEAT('a',1) | +--------------- + | a | | bbbbbbbbbb | +--------------- +
从MySQL 8.0.19开始,您还可以在可以使用等效语句的任何地方使用TABLE语句或语句。假定表和被创建并填充,如下所示:VALUESUNIONSELECTt1t2
CREATE TABLE t1(x INT, y INT);INSERT INTO t1VALUES ROW (4,-2),ROW (5,9);CREATE TABLE t2 (a INT, b INT);INSERT INTO t2VALUES ROW (1,2),ROW (3,4);
前面是这种情况,并且忽略以开头的查询的输出中的列名,VALUES以下所有UNION查询都会产生相同的结果:
SELECT *FROM t1UNION SELECT *FROM t2;TABLE t1UNION SELECT *FROM t2;VALUES ROW (4,-2),ROW (5,9)UNION SELECT *FROM t2;SELECT *FROM t1UNION TABLE t2;TABLE t1UNION TABLE t2;VALUES ROW (4,-2),ROW (5,9)UNION TABLE t2;SELECT *FROM t1UNION VALUES ROW (4,-2),ROW (5,9);TABLE t1UNION VALUES ROW (4,-2),ROW (5,9);VALUES ROW (4,-2),ROW (5,9)UNION VALUES ROW (4,-2),ROW (5,9);
您可以通过将VALUESa左侧的换行SELECT并使用别名来强制列名相同,如下所示:
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);
该SELECT语句是普通的select语句,但具有以下限制:
HIGH_PRIORITY不能与SELECT组成部分的语句一起使用UNION。如果为first指定它SELECT,则它无效。如果为任何后续SELECT语句指定它,则会导致语法错误。- 只有最后一条
SELECT语句可以使用INTO子句。但是,整个UNION结果将被写入INTO输出目标。 从MySQL 8.0.20开始,不推荐使用这两个
UNION变体,INTO并且在将来的MySQL版本中将不再支持它们:在查询表达式的结尾查询块中,使用
INTObeforeFROM会产生警告。例:...
UNION SELECT *INTO OUTFILE 'file_name'FROM table_name;在查询表达式的括号尾部,使用
INTO(无论其相对于的位置FROM)都会产生警告。例:...
UNION (SELECT *INTO OUTFILE 'file_name'FROM table_name);
弃用这些变体是因为它们令人困惑,就像它们从命名表而不是整个查询表达式(
UNION)中收集信息一样。
默认情况下,从UNION结果中删除重复的行。可选DISTINCT关键字具有相同的效果,但使其显式。使用optional ALL关键字时,不会发生重复行删除,并且结果包括所有SELECT语句中的所有匹配行。
你可以混合UNION ALL和UNION DISTINCT在相同的查询。UNION处理混合类型,以使DISTINCT联合优先ALL于其左侧的任何联合。甲DISTINCT工会可以明确,通过使用来产生UNION DISTINCT或隐式地通过使用UNION没有以下DISTINCT或ALL关键字。
在MySQL 8.0.19和更高版本中,在联合中使用一个或多个语句时UNION ALL,它们的UNION DISTINCT工作方式相同TABLE。
要应用ORDER BY或LIMIT应用于个人SELECT,请将子句放在括在括号内的括号内SELECT:
(SELECT aFROM t1WHERE a=10 AND B=1ORDER BY aLIMIT 10)UNION (SELECT aFROM t2WHERE a=11 AND B=2ORDER BY aLIMIT 10);
ORDER BY对单个SELECT语句的使用不暗示行在最终结果中出现的顺序,因为UNION默认情况下会产生一组无序的行。因此,ORDER BY在这种情况下,尽管它不一定会影响最终结果中这些行的顺序,但通常会与一起使用LIMIT,以确定要检索的选定行的子集。如果没有出现在,它被优化掉,因为它不会有任何效果,反正。SELECTUNIONORDER BYLIMITSELECT
要使用ORDER BYor LIMIT子句对整个UNION结果进行排序或限制,请在各个SELECT语句后加上括号,然后将ORDER BY或LIMIT放在最后一个语句之后。下面的示例使用两个子句:
(SELECT aFROM t1WHERE a=10 AND B=1)UNION (SELECT aFROM t2WHERE a=11 AND B=2)ORDER BY aLIMIT 10;
如前所述,不带括号的语句等效于一个带括号的语句。
从MySQL 8.0.19开始,请记住,不支持子句,可以使用ORDER BY与所示相同的方式使用and LIMITwith TABLE联合。TABLEWHERE
此类ORDER BY不能使用包含表名(即tbl_name。col_name格式的名称)的列引用。而是在第一条SELECT语句中提供列别名,并在中引用别名ORDER BY。(或者,ORDER BY使用其列位置引用该列。但是,不建议使用列位置。)
另外,如果要排序的列具有别名,则该ORDER BY子句必须引用别名,而不是列名。以下语句中的第一个是允许的,但是第二个语句失败并显示Unknown column 'a' in 'order clause'错误:
(SELECT aAS bFROM t)UNION (SELECT ...)ORDER BY b; (SELECT aAS bFROM t)UNION (SELECT ...)ORDER BY a;
要使UNION结果中的行由一个接SELECT一个的另一个行集合组成,请在每个行中选择一个额外的列SELECT用作排序列,并ORDER BY在最后一个列之后添加SELECT:
(SELECT 1AS sort_col, col1a, col1b, ...FROM t1)UNION (SELECT 2, col2a, col2b, ...FROM t2)ORDER BY sort_col;
要在各个SELECT结果中另外保持排序顺序,请在ORDER BY子句中添加第二列:
(SELECT 1AS sort_col, col1a, col1b, ...FROM t1)UNION (SELECT 2, col2a, col2b, ...FROM t2)ORDER BY sort_col, col1a;
使用附加列还使您能够确定SELECT每一行来自哪个行。额外的列也可以提供其他标识信息,例如指示表名的字符串。
UNION在ORDER BY子句中具有聚合函数的查询将被拒绝,并显示ER_AGGREGATE_ORDER_FOR_UNION错误。例:
SELECT 1AS fooUNION SELECT 2ORDER BY MAX(1);
