连接查询
含义:又称为多表查询,当查询的字段来自于多个表时,就会用到连接查询

  • 笛卡尔乘积现象:表1有m行,表2有n行,结果为m*n行

发生原因:没有有效的连接条件

  • 按年代分类:

sql92标准
sql99标准【推荐】:支持内连接+外连接(左外和右外)+交叉连接

  • 按功能分类:

内连接:

  • 等值连接
  • 非等值连接
  • 自连接
    • 外连接:
  • 左外连接
  • 右外连接
  • 全外连接
    • 交叉连接

【sql92标准】

  • 多表等值连接的结果为多表的交集部分
  • n表连接,至少需要n-1个连接条件
  • 多表的顺序没有要求
  • 一般需要为表起别名
  • 可以搭配前面介绍的所有子句使用,比如排序、分组、筛选

1、等值连接
案例一:查询女神名和对应的男神名

  1. select NAME,boyName
  2. from boys,beauty
  3. where beauty.boyfriend_id=boys.id;

案例二:查询员工名和对应的部门名

  1. select last_name,department_name
  2. from employees,departments
  3. where employees.'department_id'=departments.'department_id';
  • ①、为表起别名
  • 可以提高语句的简洁度,区分多个重名的字段
  • 注意:如果为表起了别名,则查询的字段就不能使用原来的表名去限定

案例三:查询员工名、工种号、工种名

  1. select last_name,e.job_id,job_title
  2. from employees e,jobs j
  3. where e.'job_id'=j.'job_id';
  • ②、加筛选条件

案例一:查询有奖金的员工名和部门名

  1. select last_name,department_name
  2. from employees e,departments d
  3. where e.'department_id'=d.'department_id'
  4. and e.'commission_pct' is not null;

案例二:查询城市名中第二个字符为o的对应的部门名和城市名

  1. select department_name,city
  2. from departments d,locations l
  3. where d.'location_id'=l.'location_id'
  4. and city like '_o%';
  • ③、加分组条件

案例一:查询每个城市的部门个数

  1. select count(*) 个数,city
  2. from departments d,locations l
  3. where d.'location_id'=l.'location_id'
  4. group by city;

案例二:查询有奖金的每个部门的部门名和部门领导编号和该部门的最低工资

  1. select department_name,d.manager_id,min(salary)
  2. from departments d,employees e
  3. where d.'departments_id'=e.'departments_id'
  4. and commission_pct is not null
  5. group by department_name,d.manager_id;
  • ④、加排序

案例一:查询每个工种的工种名和员工的个数,并且按员工个数降序排序

  1. select job_title,count(*)
  2. from jobs j,employees e
  3. where j.'job_id'=e.'job_id'
  4. group by job_title
  5. order by count(*) desc;
  • ⑤、实现三表查询

案例一:查询员工名、部门名的所在的城市

  1. select last_name,department_name,city
  2. from employees e,departments d,locations l
  3. where e.'department_id'=d.'department_id'
  4. and e.'department_id'=l.'department_id';

2、非等值连接
案例一:查询员工的工资和工资级别

  1. select salary,grade_level
  2. from employees e,job_grades g
  3. where salary between g.'lowest_sal' and g.'highest_sal';

3、自连接
案例一:查询员工名和上级的名称

  1. select e.last_name,e.manager_id,m.employee_id,m.last_name
  2. from employees e,employees m
  3. where e.'manager_id'=m.'employee_id';

例题:
1、显示员工表的最大工资,工资平均值

  1. select max(salary),avg(salary)
  2. from employees;

2、查询员工表的employee_id,job_id,last_name,按department_id降序,salary升序

  1. select employee_id,job_id,last_name
  2. from employees
  3. order by department_id desc,salary asc;

3、查询员工表中的job_id包含a和e的,并且a在e的前面

  1. select job_id
  2. from jobs
  3. where job_id like '%a%e%';

4、已知表student,里面有id(学号),name,gradeId(年级编号)
已知表grade,里面有id(年级编号),name(年级名)
已知表result,里面有id,score,studentNo(学号)
要求查询姓名、年级名、成绩

  1. select s.name,g.name,score
  2. from student s,grade g,result r
  3. where s.'gradeId'=g.'id'
  4. and s.'id'=r.'studentNo';

5、显示当前日期,以及去前后空格,截取子字符串的函数

  1. select now();
  2. select trim(字符 from ''); #去掉指定的字符
  3. select substr(str,起始索引,字符长度)

【sql99标准】
1、语法

  1. select 查询列表
  2. from 1 别名 【连接类型】
  3. join 2 别名
  4. on 连接条件
  5. where 筛选条件】
  6. group by 分组】
  7. having 筛选条件】
  8. order by 排序】

2、连接类型

  • 内连接(*):inner
  • 外连接(左外:left 【outer】 右外:right 【outer】 全外:full 【outer】)
  • 交叉连接:full 【outer】

一、内连接

  1. select 查询列表
  2. from 1 别名
  3. inner join 2 别名
  4. on 连接条件
  • 1、等值连接
  • 可以添加排序、分组、筛选
  • inner 可以省略
  • 筛选条件放在where后面,连接条件放在on后面,提高分离性,便于阅读
  • inner join连接和sql92语法中的等值连接效果是一样的,都是查询多表的交集

  • 案例一:查询员工名、部门名

    1. select last_name,department_name
    2. from employees e
    3. inner join departments d
    4. on e.department_id=d.department_id;
  • 【添加筛选】案例二:查询名字中包含e的员工名和工种名

    1. select last_name,job_title
    2. from employees e
    3. inner join jobs j
    4. on e.job_id=j.job_id
    5. where e.last_name like '%e%';
  • 【添加分组+筛选】案例三:查询部门个数>3的城市名和部门个数

    1. select count(*) 部门个数,city
    2. from departmentss d
    3. inner join location l
    4. on d.location_id=l.location_id
    5. group by city
    6. having 部门个数>3
  • 【添加排序】案例四:查询哪个部门的部门员工数≥3的部门名和员工个数,并按个数降序

    1. select count(*) 员工个数,department_name
    2. from departments d
    3. inner join employees e
    4. on d.department_id=e.department_id
    5. group by d.department_id
    6. having count(*)>=3
    7. order by count(*) desc;
  • 【三表连接】案例五:查询员工名、部门名、工种名,并按部门名降序

    1. select last_name,department_name,job_title
    2. from employees e
    3. inner join departments d on e.dpartment_id=d.department_id
    4. inner join jobs j on e.job_id=j.job_id
    5. group by department_name desc;
  • 2、非等值连接

  • 案例一:查询员工的工资级别

    1. select salary,grade_level
    2. from employees e
    3. join job_grades g
    4. on e.salary between g.lowest_sal and g.highest_sal;
  • 案例二:查询每个工资级别个数>20的,并且按照工资级别降序排序

    1. select count(*) 个数,grade_level
    2. from employees e
    3. join job_grades g
    4. on e.salary between g.lowest_sal and g.highest_sal
    5. group by grade_level
    6. having count(*)>20
    7. order by grade_level desc;
  • 3、自连接

  • 案例一:查询员工的名字和上级的名字

    1. select e.last_name,m.last_name
    2. from employees e
    3. join employees m on e.manager_id=m.employee_id;

    二、外连接

  • 一般用于查找一个表中有,但是另一给表中没有的纪录

  • 特点:
  1. 外连接的查询结果为主表中的所有记录,若从表中有和他匹配的,则显示匹配值,否则将会显示null
  2. 即外连接的查询结果=内连接结果+主表中有而从表中没有的纪录
  3. 左外连接,left join左边的是主表;右外连接,right join右边的是主表
  4. 左外和右外交换两个表的顺序,可以实现同样的效果
  5. 全外连接=内连接的结果+表1中有但表2中没有的+表2中有但是表1中没有的
  • 1、左外连接与右外连接
  • 案例一:查询男朋友不在男神表的女神名 ```sql select b.name,bo.*

左外连接

from beauty b left outer join boys bo

右外连接

from boys bo right outer join beauty b

on b.boyfriend_id=bo.id;

  1. - 案例二:查询哪个部门没有员工
  2. ```sql
  3. select d.*,e.employee_id
  4. from departments d
  5. left outer join employees e
  6. on d.department_id=e.department_id
  7. where e.department_id is not null;
  • 2、交叉连接
  • 相当于实现笛卡尔乘积
    1. select b.*,bo.*
    2. from beauty b
    3. cross join boys bo;
    例题:

案例一:查询编号>3的女神的男朋友信息,如果有则列出详细,如果没有则用null填充

  1. select b.id,b.name,bo.*
  2. from beauty b
  3. left outer join boys bo
  4. on b.boyfriend_id=bo.id
  5. where b.id>3;

案例二:查询哪个城市没有部门

  1. select city,d.*
  2. from departments d
  3. right outer join locations l
  4. on d.location_id=l.location_id
  5. where d.department_id is null;

案例三:查询部门名为SAL或IT的员工信息

  1. select e.*,d.department_name
  2. from departments d
  3. left join employees e
  4. on d.department_id=e.department_id
  5. where d.department_name in('SAL','IT');