1-7 用SQL进行集合运算-SQL进阶教程

导入篇:集合运算的几个注意事项

注意事项 1:SQL能操作具有重复行的集合,可以通过可选项all来支持(eg.union all)
集合运算符为了排除掉重复行,默认地会发生排序,而加上可选项all之后,就不会再排序,所以性能会有提升

注意事项 2:集合运算符有优先级
intersect比union和except优先级更高
当同时使用union和intersect,又想让union优先执行时,必须用括号明确地指定运算顺序

注意事项 3:各个DBMS提供商在集合运算的实现程度上参差不齐
SQL Server 从2005版开始支持intersect和except,而MySQL还都不支持(包含在“中长期计划”里)。还有像Oracle这样,实现了except功能但却命名为minus

注意事项 4:除法运算没有标准定义
四则运算里的和(union)、差(except)、积(cross join)都被引入了标准SQL,商(divide by)因为各种原因迟迟没能标准化

比较表和表:检查集合相等性之基础篇

在这里插入图片描述

-- 如果这个查询的结果与tbl_A及tbl_B的行数一致,则两张表是相等的
select count(*) row_cnt
from (
	select * from tbl_A
	union
	select * from tbl_B
) tmp;

原理:如果集合运算符里不加上可选项all,那么重复行就会被排除掉。因此,如果表tbl_A和表tbl_B是相等的,排除掉重复行后,两个集合是完全重合的
在这里插入图片描述
在这里插入图片描述

比较表和表:检查集合相等性之进阶篇

01. (A ⊂ B) 且 (A ⊃ B) ⇔ (A = B)
如果集合A包含集合B,且集合B包含集合A,则集合A和集合B相等
02. (A ∪ B) = (A ∩ B) ⇔ (A = B)
如果A unionB=A intersect B,则集合A和集合B相等

在这里插入图片描述
在这里插入图片描述

-- 两张表相等时返回“相等”,否则返回“不相等”
select (case when count(*)=0 then '相等' else '不相等' end) result
from (
	(select * from tbl_A
	union
	select * from tbl_B)
	except
	(select * from tbl_A
	intersect
	select * from tbl_B)
) tmp;

-- 用于比较表与表的diff
(select * from tbl_A
except
select * from tbl_B)
union all
(select * from tbl_B
except
select * from tbl_A);

用差集实现关系除法运算

01. 嵌套使用not exists
02. 使用having子句转换成一对一关系
03. 把除法变成减法(差集运算)

在这里插入图片描述
在这里插入图片描述

/*从表EmpSkills中找出精通表Skills中所有技术的员工
用求差集的方法进行关系除法运算(有余数)*/
select distinct emp
from EmpSkills ES1
where not exists(
	select skill
	from Skills
	except
	select skill
	from EmpSkills ES2
	where ES1.emp=ES2.emp
);
/*从需求的技术的集合中减去每个员工自己的技术的集合,如果结果是空集,则说明该员工具备所有的需求的技术,否则说明该员工不具备某些需求的技术*/

寻找相等的子集

在这里插入图片描述

-- 生成供应商的全部组合
select SP1.sup s1,SP2.sup s2
from SupParts SP1,SupParts SP2
where SP1.sup<SP2.sup
group by SP1.sup,SP2.sup;

在这里插入图片描述

select SP1.sup s1,SP2.sup s2
from SupParts SP1,SupParts SP2
where SP1.sup<SP2.sup -- 生成供应商的全部组合
and SP1.part=SP2.part -- 条件1 :经营同种类型的零件
group by SP1.sup,SP2.sup
-- 条件2 :经营的零件种类数相同
having count(*)=(select count(*) from SupParts SP3 where SP3.sup=SP1.sup)
and count(*)=(select count(*) from SupParts SP4 where SP4.sup=SP2.sup);

-- 如果传说中的谓词contains可以使用
select 'A contains B'
from SupParts
where(select part
	from SupParts
	where sup='A')
	contains
	(select part
	from SupParts
	where sup='B'
);

用于删除重复行的高效SQL

在这里插入图片描述

/*删除重复行:使用关联子查询
按照“商品名,价格”的组合汇总后,求出每个组合的最大rowid ,然后把其余的行都删除掉*/
delete from Products
where rowid<(
	select max(P2.rowid)
	from Products P2
	where Products.name=P2.name
	and Products.price=P2.price
);

在这里插入图片描述

-- 用于删除重复行的高效SQL语句(1):通过except求补集
delete from Products
where rowid in(
	select rowid
	from Products
	except
	seelct max(rowid)
	from Products
	group by name,price
);

在这里插入图片描述

-- 删除重复行的高效SQL语句(2):通过not in求补集
delete from Products
where rowid not in(
	select max(rowid)
	from Products
	group by name,price
);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值