想象你有两个购物车(表),一个装零食,一个装日用品。集合运算就是合并、对比这两个购物车的操作!
运算符 | 生活案例 | 默认去重 | 保留重复行 |
---|---|---|---|
UNION | 合并两个购物车 | ✔️ | UNION ALL |
INTERSECT | 找出两个购物车都有的商品 | ✔️ | INTERSECT ALL |
EXCEPT | 第一个购物车独有的商品 | ✔️ | EXCEPT ALL |
极简代码示例:
-- 合并两个班级的学生名单(自动去重)
SELECT name FROM ClassA
UNION
SELECT name FROM ClassB;
-- 查看两个购物车都有的薯片品牌(MySQL需用JOIN实现)
SELECT product FROM Cart1
INTERSECT
SELECT product FROM Cart2;
-- 查找只在Cart1出现的商品(差集)
SELECT product FROM Cart1
EXCEPT
SELECT product FROM Cart2;
列数必须相同
❌ 错误示范:SELECT 姓名,年龄 FROM 学生表 UNION SELECT 姓名 FROM 教师表
✅ 正确写法:SELECT 姓名,年龄 FROM 学生表 UNION SELECT 姓名,NULL FROM 教师表
类型要兼容
兼容组合 | 不兼容组合 |
---|---|
INT + FLOAT | VARCHAR + DATE |
CHAR(10)+CHAR(20) | BOOLEAN + INTEGER |
把多张表想象成同学录:学生表存姓名,成绩表存分数,通过学号关联!
联结类型 | 生活案例 | 关键词 | 结果集特点 |
---|---|---|---|
内联结 | 只显示有电话号码的同学 | INNER JOIN | 只保留匹配行 |
左外联结 | 所有同学显示,没号码的填无 | LEFT JOIN | 保留左表全部 |
交叉联结 | 所有同学随机组队 | CROSS JOIN | 笛卡尔积 |
代码实战:
-- 内联结:显示学生及其考试成绩(没成绩的不显示)
SELECT S.姓名, G.分数
FROM 学生表 S
INNER JOIN 成绩表 G ON S.学号 = G.学号;
-- 左外联结:所有学生显示,没成绩的标记为NULL
SELECT S.姓名, G.分数
FROM 学生表 S
LEFT JOIN 成绩表 G ON S.学号 = G.学号;
-- 交叉联结:生成所有可能的商品套餐组合(慎用!)
SELECT A.商品, B.赠品
FROM 商品表 A
CROSS JOIN 赠品表 B;
-- 过时写法(容易忘记WHERE条件导致笛卡尔积!)
SELECT * FROM 学生表, 成绩表
WHERE 学生表.学号 = 成绩表.学号;
-- ✅ 现代标准写法(清晰易懂)
SELECT * FROM 学生表
INNER JOIN 成绩表 ON 学生表.学号 = 成绩表.学号;
MySQL不支持INTERSECT/EXCEPT?看这里!
-- 使用INNER JOIN找共同好友
SELECT A.user_id
FROM 好友列表 A
INNER JOIN 好友列表 B ON A.user_id = B.user_id
WHERE A.group = '同学' AND B.group = '同事';
-- 查找只关注A没关注B的用户(左联结+IS NULL)
SELECT A.user_id
FROM 关注列表 A
LEFT JOIN 关注列表 B ON A.user_id = B.user_id AND B.target = 'B'
WHERE B.user_id IS NULL;
场景:
需求:
下期预告:《SQL高级用法》
互动话题:你在学习SQL时遇到过哪些坑?欢迎评论区留言讨论!
️温馨提示:我是[随缘而动,随遇而安], 一个喜欢用生活案例讲技术的开发者。如果觉得有帮助,点赞关注不迷路