多表查询规律总结

多表查询规律总结

1. 连接查询的分类

隐式内连接:(结构里没有inner关键字)
语法结构:select ... from 表1,表2 where 连接条件 [and 其他条件] --(外键的值等于主键的值)

显示内连接:(结构里有inner关键字,inner关键字可省略)
语法结构:select ... from a [inner] join b on 连接条件 [ where 其它条件]

左外连接:以join左边的表为主表,展示主表的所有数据,根据条件查询join右边表的数据,若满足条件则展示,若不满足则以null显示。(也可以理解为在内连接的基础上保证左边表的数据全部显示)
语法结构:select [字段][*] from 左表名 left [outer] join 右表名 on 条件

右外连接:以join右边的表为主表,展示主表的所有数据,根据条件查询join左边表的数据,若满足条件则展示,若不满足则以null显示。(也可以理解为在内连接的基础上保证右边表的数据全部显示)

内连接和外连接的区别

注意:

  1. 不管我们查询几张表,表连接查询会产生笛卡尔积,我们需要消除笛卡尔积,拿到正确的数据。我们需要找到表与表之间通过哪个字段关联起来的(通常是外键=主键)
  2. 消除笛卡尔积规律:2张表需要1个条件,3张表需要2个条件,4张表需要3个条件。(条件数 量=表的数量-1),每张表都要参与进来
2. 多表连接查询步骤:
  • 确定要查询哪些表
  • 确定表连接关系
  • 确定查询字段
  • 确定使用什么连接
3.经典案例

准备环境:建表

-- 部门表
CREATE TABLE dept (
  id INT PRIMARY KEY PRIMARY KEY, -- 部门id
  dname VARCHAR(50), -- 部门名称
  loc VARCHAR(50) -- 部门位置
);

-- 添加4个部门
INSERT INTO dept(id,dname,loc) VALUES 
(10,'教研部','北京'),
(20,'学工部','上海'),
(30,'销售部','广州'),
(40,'财务部','深圳');

-- 职务表,职务名称,职务描述
CREATE TABLE job (
  id INT PRIMARY KEY,
  jname VARCHAR(20),
  description VARCHAR(50)
);

-- 添加4个职务
INSERT INTO job (id, jname, description) VALUES
(1, '董事长', '管理整个公司,接单'),
(2, '经理', '管理部门员工'),
(3, '销售员', '向客人推销产品'),
(4, '文员', '使用办公软件');

-- 员工表
CREATE TABLE emp (
  id INT PRIMARY KEY, -- 员工id
  ename VARCHAR(50), -- 员工姓名
  job_id INT, -- 职务id
  mgr INT , -- 上级领导
  joindate DATE, -- 入职日期
  salary DECIMAL(7,2), -- 工资
  bonus DECIMAL(7,2), -- 奖金
  dept_id INT, -- 所在部门编号
  CONSTRAINT emp_jobid_ref_job_id_fk FOREIGN KEY (job_id) REFERENCES job (id),
  CONSTRAINT emp_deptid_ref_dept_id_fk FOREIGN KEY (dept_id) REFERENCES dept (id)
);

-- 添加员工
INSERT INTO emp(id,ename,job_id,mgr,joindate,salary,bonus,dept_id) VALUES 
(1001,'孙悟空',4,1004,'2000-12-17','8000.00',NULL,20),
(1002,'卢俊义',3,1006,'2001-02-20','16000.00','3000.00',30),
(1003,'林冲',3,1006,'2001-02-22','12500.00','5000.00',30),
(1004,'唐僧',2,1009,'2001-04-02','29750.00',NULL,20),
(1005,'李逵',4,1006,'2001-09-28','12500.00','14000.00',30),
(1006,'宋江',2,1009,'2001-05-01','28500.00',NULL,30),
(1007,'刘备',2,1009,'2001-09-01','24500.00',NULL,10),
(1008,'猪八戒',4,1004,'2007-04-19','30000.00',NULL,20),
(1009,'罗贯中',1,NULL,'2001-11-17','50000.00',NULL,10),
(1010,'吴用',3,1006,'2001-09-08','15000.00','0.00',30),
(1011,'沙僧',4,1004,'2007-05-23','11000.00',NULL,20),
(1012,'李逵',4,1006,'2001-12-03','9500.00',NULL,30),
(1013,'小白龙',4,1004,'2001-12-03','30000.00',NULL,20),
(1014,'关羽',4,1007,'2002-01-23','13000.00',NULL,10);

-- 工资等级表
CREATE TABLE salarygrade (
  grade INT PRIMARY KEY,
  losalary INT,
  hisalary INT
);

-- 添加5个工资等级
INSERT INTO salarygrade(grade,losalary,hisalary) VALUES 
(1,7000,12000),
(2,12010,14000),
(3,14010,20000),
(4,20010,30000),
(5,30010,99990);

–>练习1.查询所有员工信息。显示员工编号,员工姓名,工资,职务名称,职务描述 (此题考查2张表)

具体操作:
   1.确定要查询哪些表:emp e, job j
       SELECT * FROM emp e INNER JOIN job j;
    2.确定表连接条件: e.job_id=j.id
       SELECT * FROM emp e INNER JOIN job j ON e.job_id=j.id;
   3.确定查询字段:员工编号,员工姓名,工资,职务名称,职务描述
       SELECT e.`id`, e.`ename`, e.`salary`, j.`jname`, j.`description` FROM emp e INNER JOIN job j ON e.job_id=j.id;
   4.确定内连接
   select e.id,e.ename,e.salary,j.jname,j.description from emp e,job j where e.job_id=j.id;

练习1运行结果

–>练习2.查询所有员工信息。显示员工编号,员工姓名,工资,职务名称,职务描述,部门名称,部门位置 (此题考查3张表)

-- 确定要查询哪些表:emp e,job j,dept d;
-- 确定表连接关系:e.job_id=j.id and e.dept_id=d.id;
-- 确定查询字段:e.id,e.ename,e.salary,j.jname,j.description,d.dname,d.loc;
-- 确定内连接
select e.id,e.ename,e.salary,j.jname,j.description,d.dname,d.loc from emp e,job j,dept d where e.job_id=j.id and e.dept_id=d.id;

练习2运行结果

–>练习3.查询所有员工信息。显示员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级 (此题考查4张表)

-- 确定要查询哪些表:emp e,job j,dept d,salarygrade s;
-- 确定表连接关系:e.job_id=j.id and e.dept_id=d.id and e.salary between losalary and hisalary;
-- 确定查询字段:e.id,e.ename,e.salary,j.jname,j.description,d.dname,d.loc,s.grade;
-- 确定内连接
select e.id,e.ename,e.salary,j.jname,j.description,d.dname,d.loc,s.grade from emp e,job j,dept d,salarygrade s where e.job_id=j.id and e.dept_id=d.id and e.salary between losalary and hisalary; 

练习3运行结果

–>练习4.查询经理的信息。显示员工姓名,工资,职务名称,职务描述,部门名称,部门位置,工资等级 (此题考查between…and…)

-- 确定要查询哪些表:emp e,job j,dept d,salarygrade s;
-- 确定表连接关系:e.job_id=j.id and e.dept_id=d.id and e.salary between losalary and hisalary and j.jname='经理';
-- 确定查询字段:e.id,e.ename,e.salary,j.jname,j.description,d.dname,d.loc,s.grade;
-- 确定内连接
select e.id,e.ename,e.salary,j.jname,j.description,d.dname,d.loc,s.grade from emp e,job j,dept d,salarygrade s where e.job_id=j.id and e.dept_id=d.id and e.salary between losalary and hisalary and hisalary and j.jname='经理'; 

练习4运行结果

–>练习5.查询出部门编号、部门名称、部门位置、部门人数 (此题考查左外连接)

-- 子查询:查询部门人数
select dept_id,count(*) from emp e group by dept_id;
-- 确定要查询哪些表:dept d,select dept_id,count(*) total from emp e group by dept_id ;
-- 确定表连接关系:d.id=e.dept_id;
-- 确定查询字段:d.id,d.dname,d.loc,e.total;
-- 确定左外连接
select d.id,d.dname,d.loc,e.total from dept d left outer join (select dept_id,count(*) total from emp group by dept_id ) e on d.id=e.dept_id;

练习5运行结果

–>练习6.查询所有员工信息。显示员工信息和部门名称,没有员工的部门也要显示 (此题考查右外连接)

-- 确定要查询哪些表:emp e,dept d;
-- 确定表连接关系:e.dept_id=d.id;
-- 确定查询字段:e*,d.dname;
-- 确定右外连接
select e.*,d.dname from emp e right outer join dept d on e.dept_id=d.id;

练习6运行结果

–>练习7.查询所有员工信息。显示员工姓名,员工工资,职务名称,工资等级,并按工资升序排序 (此题考查排序order by)

-- 确定要查询哪些表:emp e,job j,salarygrade s;
-- 确定表连接关系:e.job_id=j.id and e.salary between s.losalary and s.hisalary and order by e.salary asc ;
-- 确定查询字段:e.ename,e.salary,j.jnamee,s.grade;
-- 确定内连接
select e.ename,e.salary,j.jname,s.grade from emp e,job j,salarygrade s where e.job_id=j.id and e.salary between s.losalary and s.hisalary order by e.salary;

练习7运行结果

–>练习8.列出所有员工的姓名及其直接上级的姓名,没有领导的员工也需要显示(此题考查一张表当作两张表用,取别名)

-- 确定要查询哪些表,emp e1, emp e2
-- 确定表连接条件 e1.mgr=e2.id
-- 确定查询字段:e1.ename,e2.ename
-- 确定左外连接
select e1.ename,e2.ename from emp e1 left outer join emp e2 on e1.mgr=e2.id;

练习8运行结果

–>练习9.查询入职期早于直接上级的所有员工编号、姓名、部门名称

-- 确定要查询哪些表,emp e1, emp e2,dept d
-- 确定表连接条件  e1.mgr=e2.id and e1.dept_id=d.id and e1.dept_id=d.id and e1.joindate<e2.joindate
-- 确定查询字段:e1.id,e1.ename,d.dname
-- 确定内连接
select e1.id,e1.ename,d.dname from emp e1, emp e2,dept d where e1.mgr=e2.id and e1.dept_id=d.id and e1.dept_id=d.id and e1.joindate<e2.joindate;

练习9运行结果

–>练习10.查询工资高于公司平均工资的所有员工信息。显示员工信息,部门名称,上级领导姓名,工资等级

-- 查询公司的平均工资
select avg(salary) from emp;
-- 确定要查询哪些表,emp e1,,emp e2,dept d,salarygrade s
-- 确定表连接条件  e1.mgr=e2.id and e1.dept_id=d.id and e1.salary between s.losalary and s.hisalary and e1.salary>(select avg(salary) from emp)
-- 确定查询字段:e1.*,d.dname,e2.ename,s.grade
-- 确定内连接
select e1.*,d.dname,e2.ename,s.grade from emp e1,emp e2,dept d,salarygrade s where e1.mgr=e2.id and e1.dept_id=d.id and e1.salary between s.losalary and s.hisalary and e1.salary>(select avg(salary) from emp);

练习10运行结果

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏目不听话

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值