第3章 表连接和集合运算

3.1 合并多个行集

想返回存储在多张表中的数据,即将多个结果集合并。这些表并非必须有相同的键,但它们的列的数据类型必须相同。

使用集合运算 UNION ALL 合并来自多张表的行。

UNION ALL 不会剔除重复的行。要剔除重复的行,可以使用运算符 UNION。使用 UNION(而不是 UNION ALL)时,很可能引发排序操作以消除重复的行。处理大型结果集时,务必牢记这一点。

除非必要,否则不要在查询中使用 DISTINCT。这条规则也适用于 UNION:除非必要,否则不要使用UNION,而应该使用 UNION ALL。

3.2 合并相关的行

想执行基于相同列或相同列值的连接,以返回多张表中的行。

基于 DEPTNO 连接 EMP 表和 DEPT 表。

select e.ename, d.loc
from emp e, dept d
where e.deptno = d.deptno
      and e.deptno = 10

另一种解决方案是显式地指定 JOIN 子句(关键字 INNER 是可选的)。

select e.ename, d.loc
from emp e 
inner join dept d    
on (e.deptno = d.deptno)
where e.deptno = 10

3.3 查找两张表中相同的行

想找出两张表中相同的行,但需要连接多列。

基于必要的列将表连接起来,以返回正确的结果。也可以使用集合运算 INTERSECT 来返回两张表的交集(两张表中相同的行),这样可以避免执行连接操作。

select e.empno,e.ename,e.job,e.sal,e.deptno
from emp e 
join V
on ( e.ename  = v.ename        
      and e.job  = v.job
      and e.sal  = v.sal )

3.4 从一张表中检索没有出现在另一张表中的值

想找出一张表(源表)中没有出现在目标表中的值

解决这个问题时,计算差集的函数很有用。DB2、PostgreSQL、SQL Server 和 Oracle 都支持差集运算。如果你使用的 DBMS 没有提供计算差集的函数,则可以像 MySQL 解决方案那样使用子查询。

select deptno from dept
except 
select deptno from emp
select d.deptno
from dept d 
where not exists (select 1     
                    from emp e
                  where d.deptno = e.deptno
                  )

3.5 从一张表中检索在另一张表中没有对应行的行

有两张包含相同键的表,你想从一张表中找出在另一张表中没有与之匹配的行。

返回一张表中的所有行,以及在另一张表中可能有匹配行也可能没有匹配行的行。然后,只留下没有匹配行的行。

select d.*
from dept d 
left outer join emp e     
on (d.deptno = e.deptno)
where e.deptno is null

3.6 在查询中添加连接并确保不影响其他连接

使用外连接来获得额外的信息,同时避免返回的数据比原来的查询少。先将 EMP 表连接到 DEPT表,以返回所有的员工及其所在的部门,然后外连接到 EMP_BONUS 表,以返回员工获得奖金的日期。

select e.ename, d.loc, eb.received
from emp e 
join dept d     
on (e.deptno=d.deptno)   
left join emp_bonus eb     
on (e.empno=eb.empno)  
order by 2

也可以使用标量子查询(放在 SELECT 列表中的子查询)来模拟外连接。

select e.ename, d.loc,
      (select eb.received 
        from emp_bonus eb          
        where eb.empno=e.empno) as received   
from emp e, dept d
where e.deptno=d.deptno  
order by 2

3.7 判断两张表包含的数据是否相同

想知道两张表或两个视图中包含的数据(包括基数和值)是否相同。

DB2 和 PostgreSQL
使用集合运算 EXCEPT 计算视图 V 和 EMP 表的差集以及 EMP 表和视图 V 的差集,然后使用集合运算UNION ALL 合并这两个差集。

 ( 
select empno,ename,job,mgr,hiredate,sal,comm,deptno,    
       count(*) as cnt    
  from V    
 group by empno,ename,job,mgr,hiredate,sal,comm,deptno    
except    
select empno,ename,job,mgr,hiredate,sal,comm,deptno,    
       count(*) as cnt   
  from emp   
 group by empno,ename,job,mgr,hiredate,sal,comm,deptno  
)  
 union all   
(  
select empno,ename,job,mgr,hiredate,sal,comm,deptno,   
       count(*) as cnt   
  from emp  
 group by empno,ename,job,mgr,hiredate,sal,comm,deptno   
except   
select empno,ename,job,mgr,hiredate,sal,comm,deptno,   
       count(*) as cnt   
  from v   
 group by empno,ename,job,mgr,hiredate,sal,comm,deptno  )

3.8 返回多张表中不匹配的行

返回多张表中不匹配的行。要返回 DEPT 表中不与 EMP 表中任何行匹配的行(没有任何员工的部门),需要使用外连接。

使用显式命令 FULL OUTER JOIN 返回两张表中匹配的行以及不匹配的行。

select d.deptno,d.dname,e.ename
from dept d 
full outer join emp e     
on (d.deptno=e.deptno)

MySQL 还不支持 FULL OUTER JOIN,因此需要使用 UNION 合并两个外连接的结果。

select d.deptno,d.dname,e.ename
from dept d 
right outer join emp e     
on (d.deptno=e.deptno)  
union 
select d.deptno,d.dname,e.ename
from dept d left outer join emp e     
on (d.deptno=e.deptno)

3.9 在运算和比较中使用NULL

NULL 与包含自己在内的任何值都不相等,也不会相等,但你想像评估实际值一样评估可为 NULL 的列返回的值。例如,你想在 EMP 表中找出业务提成(COMM)比 WARD 低的所有员工,包括业务提成为 NULL的员工。

在标准评估中,可以使用诸如 COALESCE 等函数将 NULL 转换为实际值。

select ename,comm
from emp  
where coalesce(comm,0) < ( select comm 
                            from emp                  
                           where ename = 'WARD' )

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值