5.6 进阶6:多表连接查询

Posted qifanren

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了5.6 进阶6:多表连接查询相关的知识,希望对你有一定的参考价值。

5.6 进阶6:多表连接查询

5.6.1 使用场景

  • 当查询资源来自于多个表时,就会用到连接查询
  • 现笛卡尔乘积现象
    • 定义:表1 有m行,表2有n行,结果=m*n行
    • 发生原因:不添加任何的连接条件时
    • 解决办法:添加上有效的连接条件

5.6.2 分类

  • 按年代分类
    • sql92标准:仅仅支持内连接
    • sql99标准:支持内连接+外连接(左外和右外)+交叉连接
  • 按功能分类
    • 内连接:
      • 等值连接
      • 非等值连接
      • 自链接
    • 外连接
      • 左外连接
      • 右外连接
      • 全外连接(mysql不支持)
    • 交叉连接

5.6.3 等值连接的语法和使用技巧

5.6.3.1 语法
# sql99语法:通过join关键字实现连接
select 字段,...
from 表1 别名,表2 别名
where 表1.key = 表2.key
and 筛选条件
group by 分组字段
having 分组后的筛选
order by 派去字段或表达式
【inner|left outer|right outer|cross】join 表2 on  连接条件
【inner|left outer|right outer|cross】join 表3 on  连接条件
【where 筛选条件】
【group by 分组字段】
【having 分组后的筛选条件】
【order by 排序的字段或表达式】

# 好处:语句上,连接条件和筛选条件实现了分离,简洁明了!
5.6.3.2 使用方法
  • 为表起别名:一般为表起别名,提高阅读性和性能
    • t提高语句的简介度
    • 区分多个重名的字段
    • 案例3
    • 如果为表起了别名,则查询的字段就不能使用原来的表名去限定
  • 限定条件:可以加限定条件在where后面加and,案例4
  • 多个表不分主次,没有顺序要求
  • 可以添加分组,案例6
  • 排序操作 案例8
  • 多表连接
    • 等值连接的结果 = 多个表的交集
    • n表连接,至少需要n-1个连接条件
    • 多表的顺序没有要求
    • 一般需要为表起别名
    • 可以搭配所有子句使用:排序,筛选等
    • 案例9

一、传统模式下的连接 :等值连接——非等值连接

5.6.4 非等值连接

  • 在某一个范围之内的,详见案例10

5.6.5 自连接

  • 一张表索引两次,相当于两次使用的是一张表的不同部分
    • 案例11

5.6.6 案例

案例1:查询女神名和对应的男神名称

select name, boyname
from boys,beauty
where beauty.boyfrined_id = boys.id;
  • 案例2:查询员工名和对应的部门名
select last_name, department_name
from employees, departments
where employees.department_id=departments.department_id;
  • 案例3:查询的工种号、工种号、工种名
select last_name,employees.job_id,job_title
from employees,jobs
where employees.job_id = jobs.job_id;
# 可以为表起个别名
select last_name,e.job_id,job_title
from employees e,jobs j
where e.job_id = j.job_id;
  • 案例4:查询有奖金的员工名、部门名
select last_name, department_name,e.department_id
from employees e,departments d
where e.department_id = d.department_id
and e.commission_pct is not null;
  • 案例5:查询城市命中第二个字符为o的部门名和城市名
select department_name,city
from departments d,locations l
where d.location_id=l.location_id
and city like \'_o%\';
  • 案例6:查询每个城市的部门个数
select count(*) 个数, city, d.location_id
from departments d, locations l
where d.location_id = l.location_id
group by city;
  • 案例7:查询有奖金的每个部门的部门名和部门的领导编号和该部门的最低工资
select department_name, d.manager_id, min(salary)
from departments d,employees e
where d.department_id = e.department_id
and commission_pct is not null
group by department_name,manager_id;
  • 案例8:查询每个工种的工种名和员工的个数,并且按员工个数降序
select count(*), job_title
from employees e, jobs j
where e.job_id = j.job_id
group by job_title
order by count(*) desc;
  • 案例9:查询员工名、部门名和所在城市
select last_name, department_name,city
from employees e, departments d, locations l
where e.department_id = d.department_id
and d.location_id = l.location_id
and city like \'s%\';
  • 案例10:查询出员工的工资和工资级别
select salary, grade_level
from employees e, job_grades g
where salary between g.lowest_sal and g.highest_sal
and g.grade_level = \'A\';
  • 案例11:查询员工名和上级的名称
select e.employee_id, e.last_name, m.employee_id, m.last_name
from employees e,employees m
where e.`manger_id` = m.`employee_id`;

5.6.7 sql99语法

5.6.7.1 语法
select 查询列表
from 表1 别名【连接类型】
join 表2 别名
on 连接条件
【where 筛选条件】
【having 筛选条件】
【order by排序列表】
5.6.7.2 内连接:inner
select 查询列表
from 表1 别名
inner join 表2 别名
on 连接条件;
  • 特点:
    • 添加排序、分组、筛选
    • inner可以省略
    • 筛选条件放在where后面,连接条件放在on后面,提高分离性,便于阅读
    • inner join连接和sql92语法中实现的内连接结果是相同的
5.6.7.3 自连接

详见案例

5.6.7.4 外连接
  • 应用:一个表中有,另外一个表中没有的情况
  • 特点:外连接的查询结果为主表中的所有记录
    • 如果从表中有和他匹配的,则显示匹配值
    • 如果从表中没有和他匹配的,则显示null
    • 外连接查询结果=内连接结果+主表中有而从表中没有的记录
  • 左外连接,left join左边的是主表
    右外连接,right join右边的是主表
  • 左外和右外交换两个表的顺序,可以实现同样的效果
5.6.7.5 全外连接
5.6.7.6 交叉连接

笛卡尔乘积就是交叉连接

select b.*,bo.*
from beauty b
cross join boys bo;

5.5.8 sql99案例

  • 查询员工名、部门名
select last_name, department_name
from employees e
inner join departments d
on e.department_id = d.department_id;
  • 查询名字中包含e的员工名和工种名(添加筛选)
select last_name,job_title
from employees e
inner join jobs j
on e.job_id=j.job_id
where e.last_name = like "%e%"
  • 查询部门个数>3的城市名和部门个数
# 查询每个城市的部门个数
#在1的结果上筛选
select city, count(*)
from departments d
inner join locations l
on d.location_id = l.location_id
group by city
having count(*)>3;
  • 查询那个部门的员工个数>3的部门名和员工个数,并按个数降序
select count(*), department_name
from employees e
inner join departments d
on e.department_id = d.department_id
group by department_name
having count(*)>3
order by count(*) desc;
  • 查询员工名、部门名、工种名,并按部门名降序()
select last_name,department_name,job_title
from employees e # 这个表对连接条件应该有共同的连接条件
inner join departments d on e.department_id = d.department_id
inner join jobs j on e.job_id = j.job_id
order by department_name desc;
  • 查询员工的工资级别
select salary,grade_level
from employees e
join job_grades g
on e.salary between lowest_sal and g.highest_sal;
  • 查询工资级别的个数>2的个数,并且按工资级别降序
select count(*), salary,grade_level
from employees e
join job_grades g
on e.salary between lowest_sal and g.highest_sal
group by grade_level
having count(*)>20
order by grade_level;
  • 查询员工的名字、上级的名字
select e.last_name,m.last_name
from employees e
join employees m on e.manager_id = m.employee_id
where e.last_name like "%k%";
  • 查询男朋友不在男神表的女神名
select * from beauty;
select * from boys;
# 使用左外连接实现的
select b.name, bo.*
from beauty b
left outer join boys bo
on b.boyfriend_id = bo.id
where bo.id is null;

#使用右外连接实现
select b.name, bo.*
from boys bo
right outer join beauty b
on b.boyfriend_id = bo.id
where bo.id is null;
  • 查询那个部门没有员工
# 左外
select d.*, e.employee_id
from departments d
left outer join employees e
on d.department_id = e.department_id
where e.employee_id  is null;
  • 全外连接
use girls;
select b.*, bo.*
from beauty b
full outer join boys bo
on b.boyfriend_id = bo

以上是关于5.6 进阶6:多表连接查询的主要内容,如果未能解决你的问题,请参考以下文章

MySQL基础中级进阶

Hibernate的HQL多表查询

mysql 5.6 实现排名(多表联合查询)

mysql 5.6 实现排名(多表联合查询)

mysql 5.6 实现排名(多表联合查询)

mysql 5.6 实现排名(多表联合查询)