-- 加连接条件消除笛卡尔积 select*from emp, dept where emp.dept_id = dept.id;
内连接
隐式内连接:
1 2 3 4 5 6
select 字段列表 from 表1, 表2where 连接条件;
-- 示例 select e.id, e.name, d.name from emp e, dept d where e.dept_id = d.id;
显式内连接:
1 2 3 4 5
select 字段列表 from 表1innerjoin 表2on 连接条件;
-- 示例 select e.id, e.name, d.name from emp e innerjoin dept d on e.dept_id = d.id;
要点:
内连接只查询两表交集部分的数据
没有部门的员工(dept_id为NULL)不会被查询出来
inner 关键字可省略
外连接
类型
语法
说明
左外连接
left join ... on ...
查询左表所有数据 + 右表匹配数据
右外连接
right join ... on ...
查询右表所有数据 + 左表匹配数据
1 2 3 4 5 6 7
-- 左外连接:查询所有员工(包括无部门的)及其部门名称 select e.name, d.name from emp e leftjoin dept d on e.dept_id = d.id;
-- 右外连接:查询所有部门及其员工 select e.name, d.name from emp e rightjoin dept d on e.dept_id = d.id;
要点:
外连接保留某一方所有数据,即使不满足连接条件
左外连接和右外连接可通过交换表的位置互相转换
员工列表查询应使用左外连接(保留所有员工)
子查询
SQL中嵌套select语句,称为子查询。
类型
结果
常用操作符
示例场景
标量子查询
一行一列(单值)
=, >, <, >=, <=
查询最早入职的员工
列子查询
一列多行
in, not in
查询某部门的所有员工
行子查询
一行多列
=, in
查询与某人薪资和职位相同的员工
表子查询
多行多列
作为临时表
查询每部门最高薪资的员工
标量子查询示例:
1 2 3
-- 查询最早入职的员工 select*from emp where entry_date = (selectmin(entry_date) from emp);
列子查询示例:
1 2 3 4 5
-- 查询"教研部"和"咨询部"的所有员工 select*from emp where dept_id in ( select id from dept where name ='教研部'or name ='咨询部' );
行子查询示例:
1 2 3 4 5
-- 查询与"李忠"的薪资及职位都相同的员工 select*from emp where (salary, job) = ( select salary, job from emp where name ='李忠' );
表子查询示例:
1 2 3 4
-- 获取每个部门中薪资最高的员工 select*from emp e, (select dept_id, max(salary) max_sal from emp groupby dept_id) a where e.dept_id = a.dept_id and e.salary = a.max_sal;
@Mapper publicinterfaceEmpMapper { /** 查询所有员工及其部门名称 */ @Select("select e.*, d.name as deptName from emp e left join dept d on e.dept_id = d.id") List<Emp> list(); }
要点:
使用 left join 保留所有员工(包括dept_id为NULL的)
SQL中给部门名称起别名 deptName,与Java属性名对应
开启驼峰映射后,dept_name → deptName 自动转换
4.分页查询
4.1 原始方式
Mapper接口:
1 2 3 4 5 6 7 8 9 10 11
@Mapper publicinterfaceEmpMapper { // 查询总记录数 @Select("select count(*) from emp e left join dept d on e.dept_id = d.id") Longcount(); // 分页查询(limit 起始索引, 每页条数) @Select("select e.*, d.name deptName from emp e left join dept d on e.dept_id = d.id limit #{start}, #{pageSize}") List<Emp> list(Integer start, Integer pageSize); }
@Mapper publicinterfaceEmpMapper { @Select("select e.*, d.name deptName from emp e left join dept d on e.dept_id = d.id") List<Emp> list(); // 无需传分页参数 }
<!DOCTYPE mapperPUBLIC"-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mappernamespace="com.zhang.mapper.EmpMapper"> <selectid="list"resultType="com.zhang.pojo.Emp"> select e.*, d.name deptName from emp e left join dept d on e.dept_id = d.id <where> <iftest="name != null and name != ''"> e.name like concat('%', #{name}, '%') </if> <iftest="gender != null"> and e.gender = #{gender} </if> <iftest="begin != null and end != null"> and e.entry_date between #{begin} and #{end} </if> </where> order by e.update_time desc </select> </mapper>