问题
你想返回存储在多张表中的数据,即将多个结果集合并。这些表并非必须有相同的键,但它们的列的数据类型必须相同。例如,你想显示 EMP 表中部门编号为 10 的员工的姓名和部门编号,以及 DEPT 表中每个部门的名称和编号。换言之,你希望返回如下结果集。
解决方案
使用集合运算 UNION ALL 合并来自多张表的行。
Oracle
使用聚合函数 SUM 计算薪水总额,并使用 GROUP BY 的 ROLLUP 扩展将结果组织为小计(针对不同职位)和总计(针对整张表)。
select name as name_and_dname, deptno
from emp
where deptno = 10
union all
select '----------',null
from dual
union all
select dname, deptno
from dept;
DB2、SQL Server 和 MySQL
select name as ename_and_dname, deptno
from emp
where deptno = 10
union all
select '----------', null
from t1
union all
select dname, deptno
from dept
T1为透视表(pivot table),只用于简化转置工作。T1是只包含一行数据的支持表,T1 表的用途与 Oracle 的 DUAL 表类似,但 T1 表可以让解决方案标准化。
补充
UNION ALL
UNION ALL 可以将来自多个数据源的行合并为一个结果集。与所有的集合运算一样,在 SELECT 子句中指定的列的数量和类型必须匹配。例如,下面两个查询都将以失败告终。
select deptno | select deptno, dname
from dept | from dept
union all | union all
select ename | select deptno
from emp | from emp
需要指出的是,UNION ALL 不会剔除重复的行。要剔除重复的行,可以使用运算符 UNION。例如,对 EMP.DEPTNO 和 DEPT.DEPTNO 执行 UNION 操作时,只会返回 4 行数据。
select deptno
from emp
union
select deptno
from dept
DEPTNO
---------
10
20
30
40
使用 UNION(而不是 UNION ALL)时,很可能引发排序操作以消除重复的行。处理大型结果集时,务必牢记这一点。使用 UNION 的效果与下面的查询大致相同,该查询对 UNION ALL 的输出执行了 DISTINCT 操作。
select distinct deptno
from (
select deptno
from emp
union all
select deptno
from dept
)
DEPTNO
---------
10
20
30
40
除非必要,否则不要在查询中使用 DISTINCT。这条规则也适用于 UNION:除非必要,否则不要使用 UNION,而应该使用 UNION ALL。
DUAL
- Oracle中的dual表是一个单行单列的虚拟表
- dual表是oracle与数据字典一起自动创建的一个表,这个表只有1列:DUMMY,数据类型为VERCHAR2(1),dual表中只有一个数据'X'
- Oracle有内部逻辑保证dual表中永远只有一条数据
- dual表主要用来选择系统变量或求一个表达式的值
在Oracle中,没有表名就没有办法查询,DUAL表的用途。
--查看当前连接用户
select user from dual;
--查看当前日期、时间
select sysdate from dual;
select to_char(sysdate,'yyyy-mm-dd') from dual;
--当作计算器用
select 1+2 from dual;
--查看序列值
create sequence aaa increment by 1 start with 1;
select aaa.nextval from dual;
select aaa.currval from dual;
