当前位置: 首页 > article >正文

SQL集合运算

 集合论是SQL语言的根基。

1 集合运算

注意事项:

1)SQL能操作具有重复行的集合,可以通过可选项ALL来支持。

如果直接使用UNION或INTERSECT,结果里不会出现重复的行。如果想在结果里留下重复行,可以加上可选项ALL。写作UNION ALL。

集合运算符为了排除掉重复行,会默认发生排序,而加上可选项ALL之后,就不会再排序了,所以性能会提升。

2) 集合运算符有优先级。

INTERSECT比UNION和EXCEPT的优先级更高。

1.1 实践

1.1.1 检查集合相等性

图 两个集合t_table_a与t_table_b

-- UNION,如果合并后与两个集合的行数一致,则两个集合相同
SELECT CASE 
WHEN COUNT(*) = (SELECT COUNT(*) FROM t_table_a)
AND COUNT(*) = (SELECT COUNT(*) FROM t_table_b) 
THEN '集合相等'  ELSE '集合不相等' END AS res 
FROM 
(SELECT *
FROM t_table_a
UNION
SELECT *
FROM t_table_b)tmp
-- 集合运算,如果A与B的并集等于A与B的交集。 则A=B
SELECT CASE WHEN COUNT(*) = 0 THEN '相等' ELSE '不相等' END AS res
FROM 
((SELECT *
FROM t_table_a
UNION 
SELECT *
FROM t_table_b)
EXCEPT 
(
	SELECT *
	FROM t_table_a
	INTERSECT 
	SELECT *
	FROM t_table_b
))tmp;

1.1.2 用差集实现关系除法运算

图 员工技能t_emp_skills 表与技能t_skills 表及期望输出

需求:找出精通t_skills 表所有技能的员工。

-- 差集 EXCEPT
SELECT DISTINCT emp 
FROM t_emp_skills e 
WHERE NOT EXISTS 
(
	 SELECT skill
	 FROM t_skills
	 EXCEPT 
	 SELECT skill 
	 FROM t_emp_skills 
	 WHERE emp = e.emp 
);	

需求:找出刚好拥有全部技术的员工(即擅长的技能和技能表的一摸一样,不多也不少)。

SELECT emp 
FROM t_emp_skills e 
WHERE NOT EXISTS (
	(SELECT skill
	FROM t_skills 
	EXCEPT 
	SELECT skill 
	FROM t_emp_skills
	WHERE emp = e.emp)
)
GROUP BY emp 
HAVING COUNT(*) = (SELECT COUNT(*) FROM t_skills);

1.1.3 寻找相等的子集

图 供应商-零件关系t_sup_parts表及期望输出

需求:找出经营的零件在种类数和种类上都完全相同的供应商组合。

SELECT s1.sup sup1,s2.sup sup2
FROM t_sup_parts s1
CROSS JOIN t_sup_parts s2 
WHERE s1.sup < s2.sup AND s1.part = s2.part
GROUP BY s1.sup,s2.sup
HAVING COUNT(*) = (SELECT COUNT(*) FROM t_sup_parts WHERE sup = s1.sup)
AND COUNT(*) = (SELECT COUNT(*) FROM t_sup_parts WHERE sup = s2.sup);

1.1.4 高效删除重复行

图 存在重复数据的t_fruit_info表

需求:删除表中重复的数据。

-- 使用关联子查询
DELETE FROM t_fruit_info f
WHERE row_id < (
	 SELECT *
	 FROM (
		 SELECT MAX(row_id)
		 FROM t_fruit_info 
		 WHERE `name` = f.name AND price = f.price
	 ) temp
);

关联子查询性能比较差。

-- 用差集运算 
DELETE FROM t_fruit_info
WHERE row_id IN (
	SELECT * FROM 
	(
		SELECT row_id
		FROM t_fruit_info 
		EXCEPT 
		(SELECT row_id
		FROM t_fruit_info
		GROUP BY `name`,price)
	) tmp
);
-- NOT IN 求补集 
DELETE FROM t_fruit_info
WHERE row_id NOT IN (
	SELECT * FROM 
	(
		SELECT MAX(row_id)
		FROM t_fruit_info 
		GROUP BY `name`,price
	) tmp
);

http://www.kler.cn/a/392647.html

相关文章:

  • 06.VSCODE:备战大项目,CMake专项配置
  • 阿里云和七牛云对象存储区别和实现
  • 树形dp总结
  • 4.4 软件设计:UML顺序图
  • CentOS 服务
  • 数据结构与算法-前缀和数组
  • 除了 Postman,还有什么好用的 API 管理工具吗?
  • LeetCode【0033】搜索旋转排序数组
  • C/C++基础知识复习(20)
  • LeetCode通过栈解题逆波兰表达式 有效的括号 栈的压入、弹出序列 最小栈
  • 重构代码之用委托替代继承
  • 在linux中使用nload实时查看网卡流量
  • Unity 2022 Nav Mesh 自动寻路入门
  • JavaScript高级程序设计基础(四)
  • 关系型数据库和非关系型数据库详解
  • AXI DMA IP BUG踩坑记录
  • gin入门
  • 网上商城系统设计与Spring Boot框架
  • NoSQL数据库与关系型数据库的主要区别
  • SpringMVC案例学习(一)--计算器设计登录页面设计
  • 【代码随想录day29】【C++复健】134. 加油站;135. 分发糖果;860.柠檬水找零;406. 根据身高重建队列
  • [动态规划]最长公共子序列
  • vue 计算属性get set
  • 白酒除高级醇提升口感工艺
  • Javascript高级—如何实现一个类型判断函数?
  • 基于复现油炸鸡的智能手表的过程(1)