的 Set 操作Result Set Column Names and Data TypesResult Set Column Names and Data Types
Set Operations with TABLE 和 VALUES 语句Set Operations with TABLE and VALUES Statements
使用 DISTINCT 和 ALL 的集合操作Set Operations using DISTINCT and ALL
Set Operations with ORDER BY and LIMITSet Operations with ORDER BY and LIMIT
SQL set operations combine the results of multiple query blocks
into a single result. A query block,
sometimes also known as a simple table, is
any SQL statement that returns a result set, such as
SELECT. MySQL 8.4 also
supports TABLE以及VALUES statements. See the
individual descriptions of these statements elsewhere in this
chapter for additional information.SQL set operations combine the results of multiple query blocks
into a single result. A query block,
sometimes also known as a simple table, is
any SQL statement that returns a result set, such as
SELECT. MySQL 8.4 also
supports TABLE and
VALUES statements. See the
individual descriptions of these statements elsewhere in this
chapter for additional information.
SQL 标准定义了以下三组操作:The SQL standard defines the following three set operations:
UNION:将两个查询块的所有结果合并为一个结果,省略任何重复。UNION: Combine all results from two query blocks into a single result, omitting any duplicates.INTERSECT:仅合并两个查询块结果共有的行,省略重复。INTERSECT: Combine only those rows which the results of two query blocks have in common, omitting any duplicates.EXCEPT: 对于两个查询块A和B,返回A中所有不存在于B中并未出现的结果,省略任何重复。EXCEPT: For two query blocksAandB, return all results fromAwhich are not also present inB, omitting any duplicates.(一些数据库系统,如 Oracle,使用
MINUS作为该运算符的名称。MySQL 不支持此功能。)(Some database systems, such as Oracle, useMINUSfor the name of this operator. This is not supported in MySQL.)
MySQL 支持 UNIONINTERSECT,以及 EXCEPT。MySQL supports UNION,
INTERSECT, and EXCEPT.
每一个这些集合操作符都支持一个ALL修饰符。当ALL关键字跟在集合操作符后面时,会导致结果中包含重复项。有关更多信息和示例,请参阅随后介绍各个操作符的部分。Each of these set operators supports an ALL
modifier. When the ALL keyword follows a set
operator, this causes duplicates to be included in the result. See
the following sections covering the individual operators for more
information and examples.
所有三个集合操作符也支持DISTINCT关键字,它会在结果中抑制重复项。由于这是集合操作符的默认行为,通常不需要显式指定DISTINCT。All three set operators also support a DISTINCT
keyword, which suppresses duplicates in the result. Since this is
the default behavior for set operators, it is usually not
necessary to specify DISTINCT explicitly.
通常,查询块和集合操作可以按任意数量和顺序组合。这里给出了一个极其简化的表示:In general, query blocks and set operations can be combined in any number and order. A greatly simplified representation is shown here:
query_block[set_opquery_block] [set_opquery_block] ...query_block: SELECT | TABLE | VALUESset_op: UNION | INTERSECT | EXCEPT
可以更准确、更详细地表示如下:This can be represented more accurately, and in greater detail, like this:
query_expression: [with_clause] /*WITHclause */query_expression_body[order_by_clause] [limit_clause] [into_clause]query_expression_body:query_term|query_expression_bodyUNION[ALL | DISTINCT]query_term|query_expression_bodyEXCEPT[ALL | DISTINCT]query_termquery_term:query_primary|query_termINTERSECT[ALL | DISTINCT]query_primaryquery_primary:query_block| '('query_expression_body[order_by_clause] [limit_clause] [into_clause] ')'query_block: /* also known as a simple table */query_specification/*SELECTstatement */ |table_value_constructor/*VALUESstatement */ |explicit_table/*TABLEstatement */
你应当注意,INTERSECT 在 UNION 或 EXCEPT 之前进行评估。这意味着,例如,TABLE x UNION TABLE y INTERSECT
TABLE z 总是被评估为 TABLE x UNION
(TABLE y INTERSECT TABLE z)。更多信息请参见 第 15.2.8 节,“INTERSECT 子句”。You should be aware that INTERSECT is evaluated
before UNION or EXCEPT. This
means that, for example, TABLE x UNION TABLE y INTERSECT
TABLE z is always evaluated as TABLE x UNION
(TABLE y INTERSECT TABLE z). See
Section 15.2.8, “INTERSECT Clause”, for more information.
此外,你还应当记住,虽然 UNION 和 INTERSECT 集合操作符具有交换性(顺序不重要),EXCEPT 则不具有交换性(操作数的顺序会影响结果)。换句话说,下列所有语句都是正确的:In addition, you should keep in mind that, while the
UNION and INTERSECT set
operators are commutative (ordering is not significant),
EXCEPT is not (order of operands affects the
outcome). In other words, all of the following statements are
true:
TABLE x UNION TABLE y和TABLE y UNION TABLE x产生相同的结果,尽管行的顺序可能不同。你可以使用ORDER BY强制它们顺序一致;参见 带 ORDER BY 和 LIMIT 的集合操作。TABLE x UNION TABLE yandTABLE y UNION TABLE xproduce the same result, although the ordering of the rows may differ. You can force them to be the same usingORDER BY; see Set Operations with ORDER BY and LIMIT.TABLE x INTERSECT TABLE y和TABLE y INTERSECT TABLE x返回相同的结果。TABLE x INTERSECT TABLE yandTABLE y INTERSECT TABLE xreturn the same result.TABLE x EXCEPT TABLE y和TABLE y EXCEPT TABLE x不会产生相同的结果。请参见 第 15.2.4 节,“EXCEPT 子句”,了解示例。TABLE x EXCEPT TABLE yandTABLE y EXCEPT TABLE xdo not yield the same result. See Section 15.2.4, “EXCEPT Clause”, for an example.
更多信息和示例可在随后的部分中找到。More information and examples can be found in the sections that follow.
集合操作结果的列名取自第一个查询块的列名。例如:The column names for the result of a set operation are taken from the column names of the first query block. Example:
mysql>CREATE TABLE t1 (x INT, y INT);Query OK, 0 rows affected (0.04 sec) mysql>INSERT INTO t1 VALUES ROW(4,-2), ROW(5,9);Query OK, 2 rows affected (0.00 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql>CREATE TABLE t2 (a INT, b INT);Query OK, 0 rows affected (0.04 sec) mysql>INSERT INTO t2 VALUES ROW(1,2), ROW(3,4);Query OK, 2 rows affected (0.01 sec) Records: 2 Duplicates: 0 Warnings: 0 mysql>TABLE t1 UNION TABLE t2;+------+------+ | x | y | +------+------+ | 4 | -2 | | 5 | 9 | | 1 | 2 | | 3 | 4 | +------+------+ 4 rows in set (0.00 sec) mysql>TABLE t2 UNION TABLE t1;+------+------+ | a | b | +------+------+ | 1 | 2 | | 3 | 4 | | 4 | -2 | | 5 | 9 | +------+------+ 4 rows in set (0.00 sec)
这对于 UNION、EXCEPT 和 INTERSECT 查询都是如此。This is true for UNION,
EXCEPT, and INTERSECT
queries.
每个查询块中相应位置列出的选定列应具有相同的数据类型。例如,第一个语句选择的第一列应与其他语句选择的第一列类型相同。如果相应结果列的数据类型不匹配,则结果中的列类型和长度会考虑所有查询块检索的值。例如,结果集中的列长度不受第一个语句值长度的限制,如下所示:Selected columns listed in corresponding positions of each query block 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 result columns do not match, the types and lengths of the columns in the result take into account the values retrieved by all of the query blocks. For example, the column length in the result set is not constrained to the length of the value from the first statement, as shown here:
mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',20);
+----------------------+
| REPEAT('a',1) |
+----------------------+
| a |
| bbbbbbbbbbbbbbbbbbbb |
+----------------------+
你也可以使用 TABLE 语句,或者 VALUES 语句,任何可以使用等价的 SELECT 语句。假设表 t1 和 t2 都已创建并填充,如下所示:You can also use a TABLE
statement or VALUES statement
wherever you can employ the equivalent
SELECT 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);
如前所述,且忽略查询输出中以 VALUES,以下所有 UNION 查询均得相同结果:The preceding being the case, and disregarding the column names
in the output of the queries beginning with
VALUES, 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);
为了强制列名相同,将左侧的查询块包裹为 SELECT 语句,并使用别名,如:To force the column names to be the same, wrap the query block
on the left-hand side in a SELECT statement,
and use aliases, like this:
mysql> SELECT * FROM (TABLE t2) AS t(x,y) UNION TABLE t1;
+------+------+
| x | y |
+------+------+
| 1 | 2 |
| 3 | 4 |
| 4 | -2 |
| 5 | 9 |
+------+------+
4 rows in set (0.00 sec)
,集合操作的结果中会移除重复行。可选的 DISTINCT 关键字具有相同效果,但会显式化。使用可选的 ALL 关键字,不会发生重复行的移除,结果包括并中所有查询中匹配的行。By default, duplicate rows are removed from results of set
operations. 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 queries
in the union.
You can mix ALL以及DISTINCT in the same query. Mixed types are
treated such that a set operation using
DISTINCT overrides any such operation using
ALL to its left. A
DISTINCT set can be produced explicitly by
using DISTINCT设置为UNION,
INTERSECT,或EXCEPT, or implicitly by using
the set operations with no following DISTINCT或者ALL keyword.You can mix ALL and
DISTINCT in the same query. Mixed types are
treated such that a set operation using
DISTINCT overrides any such operation using
ALL to its left. A
DISTINCT set can be produced explicitly by
using DISTINCT with
UNION,
INTERSECT, or
EXCEPT, or implicitly by using
the set operations with no following DISTINCT
or ALL keyword.
当一个或多个 TABLE 语句, VALUES 语句,或两者同时生成集合时,集合操作的原理相同。Set operations work the same way when one or more
TABLE statements,
VALUES statements, or both, are
used to generate the set.
。要对用于并集、交集或其他集合操作的单个查询块应用ORDER BY 或 LIMIT 子句,请在查询块内括号内,将子句置于括号内,如下:To apply an ORDER BY or
LIMIT clause to an individual query block
used as part of a union, intersection, or other set operation,
parenthesize the query block, placing the clause inside the
parentheses, like this:
(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); (TABLE t1 ORDER BY x LIMIT 10) INTERSECT (TABLE t2 ORDER BY a LIMIT 10);
对单个查询块或语句使用 ORDER BY 并不意味着行在最终结果中的出现顺序,因为集合操作产生的行默认是无序的。因此,ORDER BY 通常与 LIMIT一起使用,以确定要检索的选中行的子集,尽管它不一定影响最终结果中这些行的顺序。如果 ORDER
BY 在查询块中没有出现 LIMIT,则该选项被优化去除,因为它无论如何都没有影响。Use of ORDER BY for individual query blocks
or statements implies nothing about the order in which the rows
appear in the final result because the rows produced by a set
operation are by default unordered. Therefore, ORDER
BY in this context typically is used in conjunction
with LIMIT, to determine the subset of the
selected rows to retrieve, even though it does not necessarily
affect the order of those rows in the final result. If
ORDER BY appears without
LIMIT within a query block, it is optimized
away because it has no effect in any case.
要使用 ORDER BY 或 LIMIT 子句对集合操作的整个结果进行排序或限制,请将 ORDER BY 或 LIMIT 放在最后一个语句之后:To use an ORDER BY or
LIMIT clause to sort or limit the entire
result of a set operation, place the ORDER BY
or LIMIT after the last statement:
SELECT a FROM t1 EXCEPT SELECT a FROM t2 WHERE a=11 AND b=2 ORDER BY a LIMIT 10; TABLE t1 UNION TABLE t2 ORDER BY a LIMIT 10;
如果一个或多个独立语句使用了ORDER
BY, LIMIT,或者两者,并且您还希望对整个结果应用 ORDER BY、LIMIT 或两者,那么每个这样的独立语句必须用括号括起来。If one or more individual statements make use of ORDER
BY, LIMIT, or both, and, in
addition, you wish to apply an ORDER BY, LIMIT, or both to the
entire result, then each such individual statement must be
enclosed in parentheses.
(SELECT a FROM t1 WHERE a=10 AND b=1) EXCEPT (SELECT a FROM t2 WHERE a=11 AND b=2) ORDER BY a LIMIT 10; (TABLE t1 ORDER BY a LIMIT 10) UNION TABLE t2 ORDER BY a LIMIT 10;
没有 ORDER BY 或 LIMIT 子句的语句不需要加括号;在刚才显示的两个语句中,将第二个语句中的 TABLE t2 替换为 (TABLE
t2) 不会改变 UNION 的结果。A statement with no ORDER BY or
LIMIT clause does need to be parenthesized;
replacing TABLE t2 with (TABLE
t2) in the second statement of the two just shown does
not alter the result of the UNION.
您还可以在集合操作中使用 ORDER BY 和 LIMIT 来对 VALUES 语句进行操作,如下面使用 mysql 客户端的示例所示:You can also use ORDER BY and
LIMIT with
VALUES statements in set
operations, as shown in this example using the
mysql client:
mysql>VALUES ROW(4,-2), ROW(5,9), ROW(-1,3)->UNION->VALUES ROW(1,2), ROW(3,4), ROW(-1,3)->ORDER BY column_0 DESC LIMIT 3;+----------+----------+ | column_0 | column_1 | +----------+----------+ | 5 | 9 | | 4 | -2 | | 3 | 4 | +----------+----------+ 3 rows in set (0.00 sec)
(您应记住,TABLE 语句和 VALUES 语句都不接受 WHERE 子句。)(You should keep in mind that neither TABLE
statements nor VALUES statements accept a
WHERE clause.)
这种类型的 ORDER BY 不能使用包含表名的列引用(即 tbl_name.col_name 格式的名称)。 取而代之的是,在第一个查询块中提供列别名,并在 ORDER BY 子句中引用该别名。(您也可以通过列的位置在 ORDER
BY 子句中引用该列,但使用列位置的方法已被弃用,因此在未来的 MySQL 版本中可能会被移除。)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 query
block, and refer to the alias in the ORDER BY
clause. (You can also refer to the column in the ORDER
BY clause using its column position, but such use of
column positions is deprecated, and thus subject to eventual
removal in a future MySQL release.)
如果要排序的列有别名,则 ORDER
BY 子句 必须 引用该别名,而不是列名。以下语句中,第一个是允许的,但第二个会报错 Unknown column 'a' in 'order clause':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;
若要使 UNION 结果中的行按照每个查询块检索的行集合依次排列,请在每个查询块中选择一个额外的列作为排序列,并在最后一个查询块之后添加对该列进行排序的 ORDER BY 子句:To cause rows in a UNION result
to consist of the sets of rows retrieved by each query block one
after the other, select an additional column in each query block
to use as a sort column and add an ORDER BY
clause that sorts on that column following the last query block:
(SELECT 1 AS sort_col, col1a, col1b, ... FROM t1) UNION (SELECT 2, col2a, col2b, ... FROM t2) ORDER BY sort_col;
若要保持单个结果中的排序顺序,请在 ORDER BY 子句中添加第二列:To maintain sort order within individual 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 query block each row comes from. Extra columns can provide other identifying information as well, such as a string that indicates a table name.
MySQL 中的集合操作存在一些限制,下面几段将对此进行描述。Set operations in MySQL are subject to some limitations, which are described in the next few paragraphs.
包括 SELECT 语句的集合操作具有以下限制:Set operations including SELECT
statements have the following limitations:
HIGH_PRIORITY在第一个SELECT中没有影响。HIGH_PRIORITY在后续任SELECT中都会产生语法错误。HIGH_PRIORITYin the firstSELECThas no effect.HIGH_PRIORITYin any subsequentSELECTproduces a syntax error.只有最后一个
SELECT语句可以使用INTO子句。然而,整个UNION结果会写入INTO输出目标。Only the lastSELECTstatement can use anINTOclause. However, the entireUNIONresult is written to theINTOoutput destination.
这两个包含 UNIONThese two UNION variants containing
INTO are deprecated; you should expect
support for them to be removed in a future version of MySQL:
在查询表达式的后置查询块中,使用
INTO前FROM会触发警告。示例:In the trailing query block of a query expression, use ofINTObeforeFROMproduces a warning. Example:... UNION SELECT * INTO OUTFILE '
file_name' FROMtable_name;在查询表达式的括号尾块中,使用
INTO(无论其相对于FROM的位置,都会发出警告。示例:In a parenthesized trailing block of a query expression, use ofINTO(regardless of its position relative toFROM) produces a warning. Example:... UNION (SELECT * INTO OUTFILE '
file_name' FROMtable_name);这些变体被弃用是因为它们令人困惑,好像它们从命名表中获取信息,而非整个查询表达式(
UNIONThose variants are deprecated because they are confusing, as if they collect information from the named table rather than the entire query expression (theUNION).
在 ORDER
BY被拒绝 ER_AGGREGATE_ORDER_FOR_UNION。虽然错误名称可能暗示这只限于UNION 查询,但上述内容同样适用于 EXCEPT 和 INTERSECT,如此处所示:Set operations with an aggregate function in an ORDER
BY clause are rejected with
ER_AGGREGATE_ORDER_FOR_UNION.
Although the error name might suggest that this is exclusive to
UNION queries, the preceding is also true for
EXCEPT and INTERSECT
queries, as shown here:
mysql> TABLE t1 INTERSECT TABLE t2 ORDER BY MAX(x);
ERROR 3028 (HY000): Expression #1 of ORDER BY contains aggregate function and applies to a UNION, EXCEPT or INTERSECT
锁定子句(如 FOR UPDATE 或 LOCK IN SHARE MODE适用于其所跟随的查询块。这意味着,在用于集合操作的 SELECT 语句中,只有当查询块和锁定子句被括号包住时,锁定子句才可以使用。A locking clause (such as FOR UPDATE or
LOCK IN SHARE MODE) applies to the query
block it follows. This means that, in a
SELECT statement used with set operations, a
locking clause can be used only if the query block and locking
clause are enclosed in parentheses.