_14_ 组合查询
本文DEMO
https://gitee.com/changsanjiang/SQLDemo/tree/master
多数SQL查询只包含从一个或多个表中返回数据的单条SELECT语句. 但是SQL也允许执行多个查询(多条SELECT语句), 并将结果作为一个查询结果集返回. 这些组合查询通常称为并(union)或复合查询(compound query).
主要有两种情况需要使用组合查询:
- 在一个查询中从不同的表返回结果数据
- 对一个表执行多个查询, 按一个查询返回数据
下面我们来看如何利用UNION
操作符将多条 SELECT语句 组合成一个结果集.
创建组合查询
可用 UNION 操作符来来组合数条SQL查询. 利用 UNION, 可给出多条SELECT语句, 将他们的结果组合成一个结果集.
举个例子, 假如需要 Illinois, Indiana 和 Michigan 等美国几个州的所有顾客的报表, 还想包括不管位于哪个州的所有的 Fun4All. 当然可以利用 WHERE子句来完成此工作, 不过这次我们使用 UNION.
如果所述, 创建 UNION设计编写多条SELECT语句. 首先来看单条语句:
SELECT cust_name, cust_contact, cust_email, cust_state![屏幕快照 2018-07-26 上午9.00.21.png](https://img.haomeiwen.com/i2318691/9f153b35a378371f.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
FROM Customers
WHERE cust_state IN ('IL', 'IN', 'MI');
SELECT cust_name, cust_contact, cust_email, cust_state
FROM Customers
WHERE cust_name = 'Fun4All';
分析:
第一条 SELECT 把几个州的缩写传递给 IN 子句, 检索出这些州的所有行.
第二条 SELECT 利用简单的相等测试找出所有的 Fun4All.
组合这两条语句, 可以如下进行:
SELECT cust_name, cust_contact, cust_email, cust_state
FROM Customers
WHERE cust_state IN ('IL', 'IN', 'MI')
UNION
SELECT cust_name, cust_contact, cust_email, cust_state
FROM Customers
WHERE cust_name = 'Fun4All';
输出:
屏幕快照 2018-07-26 上午9.00.21.png分析:
这条语句由前面的两条SELECT语句组成, 之间用UNION关键字分隔. UNION 指示DBMS执行这两条SELECT语句, 并把输出组合成一个查询结果集.
为了便于参考, 这里给出使用多条WHERE子句的SQL语句:
SELECT cust_name, cust_contact, cust_email, cust_state
FROM Customers
WHERE cust_state IN ('IL', 'IN', 'MI') OR cust_name = 'Fun4All';
提示: UNION的限制
使用UNION组合SELECT语句的数目, SQL 没有标准限制. 但是最好是参考一下具体的DBMS文档, 了解他是否对 UNION能组合的最大语句数目有限制.
注意: 性能问题
多数好的DBMS使用内部查询优化程序, 在处理各条SELECT语句前组合他们. 理论上讲, 这意味着从性能上看使用多条WHERE子句条件还是UNION应该没有实际的差别. 不过我说的是理论上, 实践中多数查询优化程序并不能达到理想状态, 所以最好测试一下这两种方法, 看哪种工作得更好.
UNION 规则
可以看到, UNION非常容易使用, 但在进行组合时需要注意几条规则.
- UNION 必须由两条或两条以上的SELECT语句组成, 语句之间用关键字UNION分隔(因此, 如果组合四条SELECT语句, 将要使用三个UNION关键字)
- UNION中的每个查询必须包含相同数量的列, 表达式或聚集函数. 如开始的SELECT中的四个列, 第二个SELECT中同样也有四个列
- 列数据必须兼容: 类型不必完全相同, 但必须是DBMS可以隐含转换的类型(例如, 不同的数值列席或不同的日期类型)
组合查询 结果排序
SELECT语句的输出用ORDER BY子句排序. 在用UNION组合查询时, 只能使用一条ORDER BY子句, 它必须位于最后一条SELECT语句之后. 对应结果集, 不存在用一种方式排序一部分, 而有用另一种方式排序另一部分的情况, 因此不允许使用多条ORDER BY子句.
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_state IN ('IL', 'IN', 'MI')
UNION
SELECT cust_name, cust_contact, cust_email
FROM Customers
WHERE cust_name = 'Fun4All'
ORDER BY cust_name, cust_contact;
输出:
image.png分析:
这条UNION在最后一条SELECT语句后使用ORDER BY子句. 虽然ORDER BY子句似乎只是最后一条SELECT语句的组成部分, 但实际上DBMS将用它来排序所有SELECT语句返回的所有结果.
提示: 操作多个表
以上例子都是使用UNION来组合针对同一表的多个查询. 实际上, UNION 在需要组合多个表的数据时也很有用, 即使列名不同, 在这种情况下, 可以将UNION与别名组合, 从而检索一个结果集.