开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 28 天,点击查看活动详情
本节主要记录了如何使用 UNION
操作符将多条 SELECT
语句组合成一个结果集。
组合查询
大多数 SQL
查询都是只包含了单条 SELECT
语句。现在,我们还可以使用 UNION
操作符来组合多条 SQL
查询,让 MySQL 执行多条 SELECT
语句,并将结果作为单个查询结果集返回。
这种多条 SELECT
语句组合查询的情况通常被称为并(union
)查询 或者 复合(compound
)查询。
组合查询和多个
WHERE
条件:
- 多数情况下,组合相同表的两个查询完成的工作与具有多个
WHERE
子句条件的单条查询完成的工作相同。- 换句话说,任何具有多个
WHERE
子句的SELECT
语句都可以作为一个组合查询给出。
创建组合查询
使用 UNION
先来看两个例子:
- 检索价格小于等于 100 的所有产品:
select
vend_id, prod_id, prod_price
from
products
where
prod_price <= 100;
- 检索 供应商ID 为 1001 和 1009 生产的所有物品:
select
vend_id, prod_id, prod_price
from
products
where
vend_id in (1001, 1009);
- 现在,我们使用
UNION
操作符来组合这两条SQL
查询:
select
vend_id, prod_id, prod_price
from
products
where
prod_price <= 100
union
select
vend_id, prod_id, prod_price
from
products
where
vend_id in (1001, 1009);
记录:
- 可以看到,
UNION
操作符将两条SELECT
语句组合在一起,其中,两条语句用UNION
关键字分隔。 - 也就是说,
UNION
操作符指示 MySQL 执行两条SELECT
语句,并将输出组合成单个查询结果集。
另一方面,我们也意识到,这个组合查询可以使用多条 where
子句进行代替,如下所示:
select
vend_id, prod_id, prod_price
from
products
where
prod_price <= 100 or vend_id in (1001, 1009);
事实上,无论是组合查询还是使用多个
WHERE
条件,都是可行的。这两种技术在不同的查询中性能也不同。对于复杂的过滤条件或者从多个表中检索数据的情况时,使用组合查询可能会使处理更简单。
注意事项
在使用组合查询时(UNION
),注意事项如下:
union
操作符必须由两条或两条以上的select
语句组成,语句之间用关键字union
进行分隔(组合 3 条select
语句将要使用 2 个union
操作符)union
组合的每个查询语句必须包含相同的列、表达式或聚集函数(次序不要求)- 列数据必须兼容,数据类型不必完全相同,但是必须是 MySQL 中可以隐含地转换的类型。
- 在使用
union
进行组合查询时,只能使用一条order by
子句(不允许使用多条order by
子句)
包含或取消重复的行
union
操作符在查询时有一个默认行为,即从查询结果集中自动去除了重复的行。
比如之前我们记录的例子:
select
vend_id, prod_id, prod_price
from
products
where
prod_price <= 100
union
select
vend_id, prod_id, prod_price
from
products
where
vend_id in (1001, 1009);
在上述例子中:
- 第一条
select
语句返回了 4 行数据,第二条select
语句返回了 5 行数据,但是使用union
操作符组合两条select
语句后返回了 8 行数据(而不是 9 行)。 - 这是因为在第二条查询语句中,供应商 1009 生产的一种产品,价格也低于 100。而
union
操作符从查询结果集中自动去除了重复的行(这种默认行为和使用多条where
子句的效果一样)
如果我们想要改变这种 union
操作符的默认行为,使得所有的匹配行都可以返回,此时可以使用 union all
。
比如:
select
vend_id, prod_id, prod_price
from
products
where
prod_price <= 100
union all
select
vend_id, prod_id, prod_price
from
products
where
vend_id in (1001, 1009);
记录:
union all
是union
的一种形式,它完成了where
子句完成不了的工作- 如果确实需要每个条件的匹配行全部出现(包括重复行),则必须使用
union all
而不是 多条where
子句。
小结
在哪些情况下可以尝试使用组合查询呢?
如下所示:
- 在单个查询中从不同的表返回类似结构的数据
- 对单个表执行多个查询,按单个查询返回数据