SQL 入门笔记(十四)组合查询
本节将讲述如何利用 UNION
操作符将多条 SELECT
语句的结果组合成一个结果集
组合查询
多数 SQL 查询只包含从一个或多个表中返回数据的单条 SELECT
语句。但是,SQL 也允许执行多个查询(多条 SELECT
语句),并将结果作为一个查询结果返回。这些组合查询通常被称为 并(union)
或 复合查询(compound query)
主要有两种情况需要使用组合查询:
- 在一个查询中从不同的表返回数据结构
- 对一个表执行多个查询,按一个查询返回数据
说明:组合查询和多个 WHERE 条件
多数情况下,组合相同表的两个查询所完成的工作与具有多个 WHERE 子句条件的一个查询所完成的工作相同。换句话说,任何具有多个 WHERE
子句的 SELECT
语句都可以作为一个组合查询,在下面可以看到这一点
创建组合查询
使用 UNION
很简单,只需要在各条 SELECT
之间加上 UNION
就好了
举个例子,假如需要 Illinois、Indian 和 Michigan 等美国几个州的所有顾客的报表,还想包括不管位于那个州的所有的 Fun4All
这当然可以使用 WHERE
子句,例如下面这样
1 | SELECT cust_name, cust_contact, cust_email |
而如果使用 UNION
,则会是这样
1 | SELECT cust_name, cust_contact, cust_email |
在这个简单的例子中,使用 UNION
的确比使用 WHERE
更加复杂。但是对于较复杂的过滤条件,或从多个表(而不是一个表)中检索数据的情形,使用 UNION
可能会更简单
提示:UNION 的限制
使用 UNION
组合 SELECT
语句的数目,SQL 没有标准限制,但是 DBMS 可能会有限制
UNION 规则
可以看到,UNION
非常容易使用,但在进行组合时需要注意几条规则
UNION
必须由两条或两条以上的SELECT
语句组成,语句之间使用UNION
分隔UNION
中的每个查询必须包含相同的列、表达式或聚集函数(不过各个列不需要以相同的次序列出)- 列数据类型必须兼容:类型不必完全相同,但是必须是 DBMS 可以隐式转换的类型
提示:UNION 的列名
如果结合的两个查询使用不同的列名,那会返回什么名字呢?例如第一个语句是 SELECT prod_name
,而第二个是 SELECT productname
答案是使用第一个名字,举得这个例子会返回 prod_name
,而不管第二个名字。这意味着你可以对第一个名字使用别名,而自定义返回的列名。同时如果排序的话也只能使用第一个名字
包含或取消重复的行
如果你单独执行上面被组合起来的两个查询语句,你会发现第一条会返回 3 行,第二条会返回 2 行,而且这两组结果中有一行是相同的
但是将这两个组合在一起,就只会返回 4 行,而不是 5 行,可见 UNION
默认会自动去重
如果需要改变这一点,可以使用 UNION ALL
,这样会返回所有的匹配行
1 | SELECT cust_name, cust_contact, cust_email |
前面说过, UNION
几乎总是完成与多个 WHERE
条件相同的工作。但是 UNION ALL
作为 UNION
的一种形式,它能完成 WHERE
不能完成的工作
对组合查询结果排序
SELECT
语句使用 ORDER BY
子句排序,在用 UNION
组合查询时,只能用一条 ORDER
BY 子句,它必须在最后一条 SELET
语句之后。对于结果集,不能使用一种方式排序一部分,而又用另一种方式排序另一部分,因此不允许使用多条 ORDER BY
子句
下面的例子对前面 UNION 返回的结果进行排序
1 | SELECT cust_name, cust_contact, cust_email |
虽然 ORDER BY
子句看上去只是最后一条 SELECT
的一部分,但实际上它对整个结果集进行排序
说明:其他类型的 UNION
某些 DBMS 还支持另外两种 UNION
:
EXCEPT
(有时称为MINUS
),检索只在第一个表中存在而第二个表中不存在的行INTERSECT
,检索两个表中都存在的行
实际上,这些 UNION
很少使用,因为相同的结果可以通过联结得到
提示:操作多个表
本节的例子都是使用 UNION
来组合查询一个表,但是 UNION
在需要组合多个表的数据时也很有用,即使是有不匹配的列名的表