Tlias管理系统(多表查询-内连接外连接)
用“两张纸+剪刀+胶水”的比喻,30 秒让你肉眼看懂:
把 emp 表打印在绿色纸上,dept 表打印在黄色纸上。
两纸叠一起,沿着 emp.dept_id = dept.id 剪洞,把能对得上的行钉在一起——这就是内连接的结果,只拿到“钉住”的那部分。
现在换外连接:
左外连接 = 绿色纸整张保留,黄色纸对不上就撕掉,撕掉的地方用空白透明胶补上(NULL)。
右外连接 = 黄色纸整张保留,绿色纸撕掉,空白处补 NULL。
全外连接 = 两张纸都保留,能钉就钉,钉不上就各自补空白。
1. 内连接(INNER JOIN)——只留“对得上”的行
SELECT *
FROM emp
JOIN dept ON emp.dept_id = dept.id; -- 或 INNER JOIN
结果:
员工表里 dept_id 为 NULL 或写错 → 丢弃
部门表里没有对应 id → 丢弃
行数 ≤ min(emp行, dept行),本例 14 → 10 行
2. 外连接(OUTER JOIN)——对不上也保留,空位补 NULL
表格
复制
类型 | 保留谁 | 补 NULL 方 | 示例行数 | 场景 |
---|---|---|---|---|
LEFT | 左表(emp) | 右表(dept) | 14 行 | “列出所有员工,不管有没有部门” |
RIGHT | 右表(dept) | 左表(emp) | 4 行 | “列出所有部门,不管有没有员工” |
FULL | 两边都保留 | 对侧缺就补 NULL | 18 行 | “员工和部门全展示,谁缺就空” |
-- 左外
SELECT * FROM emp LEFT JOIN dept ON emp.dept_id = dept.id;-- 右外
SELECT * FROM emp RIGHT JOIN dept ON emp.dept_id = dept.id;-- 全外(MySQL 8 无,需 UNION)
SELECT * FROM emp LEFT JOIN dept ON ...
UNION
SELECT * FROM emp RIGHT JOIN dept ON ...;
3. 一张脑图秒记
JOIN 结果 =内连接:交集(对得上才要)左外:左表全集 + 右表匹配(无则NULL)右外:右表全集 + 左表匹配(无则NULL)全外:左右全集,能匹配就合并,不能就各补NULL
4. 一句话总结
内连接是“严格配对”,外连接是“保留全集,对不上就 NULL”;
写报表、补缺失数据时,外连接才是救命稻草。
业务里“主表”永远在左边,而我们要的是“主表数据一条不能少”——于是 LEFT JOIN 成了默认答案。
-- ======================================多对多=============================
create table tb_student(id int auto_increment primary key comment '主键ID',name varchar(10) comment '姓名',no varchar(10) comment '学号'
) comment '学生表';
insert into tb_student(name, no) values ('黛绮丝', '2000100101'),('谢逊', '2000100102'),('殷天正', '2000100103'),('韦一笑', '2000100104');create table tb_course(id int auto_increment primary key comment '主键ID',name varchar(10) comment '课程名称'
) comment '课程表';
insert into tb_course (name) values ('Java'), ('PHP'), ('MySQL') , ('Hadoop');create table tb_student_course(id int auto_increment comment '主键' primary key,student_id int not null comment '学生ID',course_id int not null comment '课程ID',constraint fk_courseid foreign key (course_id) references tb_course (id),constraint fk_studentid foreign key (student_id) references tb_student (id)
)comment '学生课程中间表';insert into tb_student_course(student_id, course_id) values (1,1),(1,2),(1,3),(2,2),(2,3),(3,4);#多表设计 dept(1) ---> emp(n) emp(1)-->emp_expr(n)
create table emp_expr(begin date comment '开始时间',end date comment '结束时间',company varchar(50) comment '公司名称',job varchar(50) comment '职位名称',emp_id int unsigned comment '员工ID',
)comment '工作经历表'
select * from emp ,dept;
##========
##A.查询所有员工的id 姓名 及所属的部门名称(显式隐式实现)
##隐式 消除笛卡尔积
select emp.id,emp.name,dept.name from emp,dept where emp.dept_id=dept.id;##显式
select emp.id,emp.name,dept.name from emp inner join dept on emp.dept_id = dept.id;
select emp.id,emp.name,dept.name from emp join dept on emp.dept_id = dept.id;##B.查询性别为男工资高于8000员工id姓名及所属部门名称
#隐式
select emp.id,emp.name,dept.name from emp,dept where emp.dept_id=dept.id and emp.gender = 1 and emp.salary > 8000;##显式
select emp.id,emp.name,dept.name from emp inner join dept on emp.dept_id = dept.id where emp.gender = 1 and emp.salary > 8000;
select emp.id,emp.name,dept.name from emp join dept on emp.dept_id = dept.id where emp.gender = 1 and emp.salary > 8000;
##起别名
select e.id,e.name,d.name from emp e join dept d on e.dept_id = d.id where e.gender = 1 and e.salary > 8000;#A.查询员工表所有员工的姓名 对应部门名称(左外连接)
select emp.name,dept.name from emp left outer join dept on emp.dept_id = dept.id;
#B.查询员工表所有员工的姓名 对应部门名称(右外连接)
select dept.name,emp.name from emp right outer join dept on emp.dept_id = dept.id;
select dept.name,emp.name from emp right join dept on emp.dept_id = dept.id;
#C查询工资高于8000所有员工姓名 与对应部门(左外连接)
select dept.name,emp.name from emp left join dept on emp.dept_id = dept.id where emp.salary > 8000;