组合查询:并(union)
复合查询(compound query):也称并,执行多个查询(多条select 语句),并将结果作为单个结果集返回。
使用场景:
1、在单个查询中从不同的表返回类似结构的数据;
2、对单个表执行多个查询,按单个表查询返回数据
注意:任何具有多个where 子句的select 语句都可以作为一个组合查询,而且这两种技术在不同的查询中性能也不同,所以使用时可以测一下哪个更快。
简单使用
1、创建组合查询 : 借助 union 操作符组合数条sql 查询,并将结果组合成单个结果集
主要就是:多条select 语句之间使用 union 分开,并且他们需要查询的列一致
来个小例子:
将一个商品小于等于5 或 供应商是1001 和1002 的商品列出
我这一描述,你是不是就想到了 where 子句 结合 or 操作符
这当然可以,刚才说 任何具有多个where 子句的select 语句都可以作为一个组合查询,的意思就是这个,
因为,他的实现方式就是先执行一where 子句将 商品小于等于5 筛选出来
select vend_id,prod_id,prod_price from products where prod_price <=5;
在执行一where 子句将 供应商是1001 和1002 的 筛选出来
select vend_id,prod_id,prod_price from products where vend_id IN(1001,1002);
由于需要返回出来的列相同,最后将返回出来的结果合并,重复的只要一条
返回的结果就是下面这个,用 or 和 in操作符查出来的
select vend_id,prod_id,prod_price from products where prod_price <=5 or vend_id in(1002,1003);
用 组合查询 union 操作符实现
--多条 sql 之间使用 union 连接,注意返回的结构要一致
select vend_id,prod_id,prod_price fromproductswhere prod_price <= 5 union
select vend_id,prod_id,prod_price fromproductswhere vend_id in(1001,1002);
千万要注意: 返回的 列的数目要一致,不然报错
在这个小例子中使用,有两个感觉一个是理解起来很容易,另一个就是书写起来繁琐,但是在复杂的过滤条件或从多个表中检索数据时就可以极大的简化复杂的where 子句或简化从多个表中检索数据的工作
注意:union 的规则
1、union 必须由两条或两条以上的select 语句组成,语句之间用关键字union 分隔。
2、union 中每个查询必须包含相同的列、表达式或聚集函数,不过个个列之间的次序不做要求
3、列数据类型必须兼容,就是列数据的类型可以不完全相同,但要可以相互转换,如不同的数值类型之间(由于转换可能会出现数据不准的现象,所以建议类型完全相同时使用)
2、对重复行的控制 (包含 union all 或取消 union)
union 默认自动将重复取消,如果想要包含可以与 all 连用使用 union all
mysql> select vend_id,prod_id,prod_price from products where prod_price <= 5
-> union all
-> select vend_id,prod_id,prod_price from products where vend_id in(1001,1002);
虽然 union 几乎总是完成与多个where 条件相同的工作, 但是union all( 是union 的一种形式)完成了where 子句完成不了的工作,将重复行也检索出来。
3、对组合查询的结果排序:只能使用一条order子句,而且必须放在最后一条select 语句中。
select vend_id,prod_id,prod_price from products where prod_price <= 5
union all
select vend_id,prod_id,prod_price from products where vend_id in(1001,1002)order by vend_id,prod_price;
虽然放在的是最后一条语句上,但是由于返回的列都相同,所以它的排序是针对所有select 语句的。
进阶思考
你是不觉得:
要是在三个乃至更多个表时,他们之间的列会有所冗余,因为不同表的列也不同啊,
是不是查询不同的表,要使用两个表之间共有的字段;
mysql> select vend_id from products where prod_price <=5
-> union
-> select vend_id from vendors where vend_id in(1001,1002);
如要要是这样那这个特性不就没啥用了吗
注意:之前说的是类似结构所以,真不表中没有字段,可使用 0 as 列名 代替
就想下面这样,将不同表独有字段展示出来