MySQL之DQL语句

文章目录

      • 查询语句
        • 条件运算符
        • 条件查询
        • 模糊查询
        • 排序查询
        • 分组函数
          • count()
          • sum()
          • avg()
          • max()、min()
        • 分组统计
        • 多表查询
          • 连接查询
            • 分类
            • 内、外连接
          • 笛卡尔积
          • 内连接
            • 等值连接
            • 非等值连接
            • 自连接
          • 外连接
            • 左外连接
            • 右外连接
          • 多表查询
        • 子查询
          • 临时结果
            • 多列匹配
          • 临时表
        • 合并查询
        • 分页查询
        • sql执行顺序

查询语句

  • DQL:数据库查询语句
  • DQL 字句执行顺序
    • from → where → group by → having → select → order by

条件运算符

类型 运算符 作用
between...and... 在某一区间(闭区间)
in(set) 在 in 列表中的任一值(非区间);例如:in(100,200)
like 模糊查询,包含
not like 模糊查询,不包含
is null 为空
is not null 不为空
not 不成立;例如:where not (salary = 5000)
比较 > 、< 、<= 、>= 、= 、!=(<>) 大于、小于、小于等于、大于等于、等于、不等于
逻辑 and 多条件同时成立
or 多条件任一成立
  • MyBatisMapper 文件中 使用运算符会将 < 标记为尖括号
    • 使用 使编译器忽略 [] 里内容
      • 或使用 $lt;表示 <
      • 使用 >表示 >,在 MyBaits> 可直接使用
    • 替换符号可直接和运算符连接使用
      • <= 表示 <=

条件查询

  • 查询指定字段(column)的数据

    • 多个字段 , 隔开
    • * 代表查询所有字段
      • 实际开发不建议使用,全字段查询效率较低
    • from:要查询的表
    • where:筛选字段的条件
  • 字段可以参与数学运算

    • 计算的字段都为都为数值类型
  • distinct:去除查询出的完全一样的记录

    • 只能在所有字段最前面

    • 不能用在中间指定某一个字段

  • as:指定查询的字段在查询结果中的暂时别名

    • 可省略
-- 从 student 表中查询每个学生的总分,显示姓名和总成绩
select [distinct] * /* 或 column1, column2... */ from `table_name` where 限定条件;

-- 语文、数学、英语成绩相加查询显示为一列,取别名 total
select `name`, (Chinese + Math + English) as total from student

模糊查询

  • like:模糊查询
    • %:表示任意多个字符
    • _:(下划线)表示任意单个字符
  • not like
like '%A%';				-- 含有A的记录
like '%A';				-- 以 A 结尾
like 'A%';				-- 以 A 开头
like '__A%';			-- 第三个字母为 A,两个下划线
like '%\_%';			-- 转义字符使用,含有 _ 的记录
not like '%A%';			-- 不包含 A 的记录

排序查询

  • order by 指定排序的列,排序的的列可以是表中的列名,也可以是指定的别名
    • asc 升序(默认)
    • desc 降序
    • 可根据字段顺序排列
      • order by 2:根据第二个字段排序
      • 字段顺序发生改变后查询结果错误
  • order by 子句应位于 select 语句的结尾
    • 指定按多列排序 , 分隔
    • 前一轮排序相等才进入下一轮排序
  • 执行顺序
    • from → where → group by → having → select → order by
select column1 as name from `table_name` order by `column1` /*或 name */ asc /*或 desc*/
-- 查找姓李的数学成绩降序,语文成绩升序排列(显示姓名、数学成绩、语文成绩)
select name,math,chinese from student where name like '李%' order by math desc, chinese asc

分组函数

  • 又叫多行处理函数
    • 处理多行数据,最终输出一行
  • 自动忽略 null
    • 统计结果时 null 不参与
  • 不可直接使用在 where 语句中
    • 通常 分组函数 和 group by 联合使用
      • 且 分组函数 在 group by 之后执行
      • group bywhere 之后执行
    • 没有显式声明 group by 时整表作为一组执行
  • 可组合使用
count()
  • 统计函数
    • count(*):统计满足条件的总记录条数
      • 与某字段无关
      • 或使用 count(常量) 效果一样
    • count(字段):统计此字段满足条件且不为 null 的记录数
select count(*)/* count(列名) */ from `table_name` where 限定条件
-- 统计姓名不为空的数学成绩大于80的总人数
select count(name) from student where math > 80
sum()
  • sum() 返回该列满足 where 条件的行的和
    • 适用于数值列,仅对数值起作用
    • 对多列分别求和时 , 不能少
select sum(列名), sum(列名) from `table_name` where 限定条件
-- 求出所有人的数学总成绩之和 及 英语和语文总成绩之和
select sum(Math), sum(English + Chinese) from student
avg()
  • 返回满足条件的字段的平均值
select avg(列名), avg(列名) from `table_name` where 限定条件
-- 求一个班数学平均分和总分平均分
select avg(Math),avg(Math + English + Chinese) from student
max()、min()
  • 返回满足条件的所有记录中的最值
select max(列名) /* min(列名) */ from `table_name` where 限定条件
-- 求班级最高分和最低分指定为max、min
select max(Math + English + Chinese) as 'max',min(Math + English + Chinese) as 'min' from student

分组统计

  • group by:根据某字段分组
    • 对查询结果分组统计
    • 多字段联合分组 , 分隔
      • 先按照前面字段分组
    • group by 分组时 select 只能查询分组相关字段和 分组函数
      • 即 select 后字段必须使用分组函数或出现在 group by 后
      • Oracle 中语法严格会直接报错
      • MySQL 中语法比较松散可以执行
        • 但查询其他字段毫无意义,会随机显示该字段记录
  • having:筛选记录
    • 限制分组显示结果
    • 必须跟在 group by 后面
  • 执行顺序
    • from → group by → select
    • 通常 分组函数 和 group by 联合使用
      • 且 分组函数 在 group by 之后执行
    • 未显式声明 group by 时整张表作为一组执行
-- group by 分组;分组后使用 having 字句进行过滤
select column1 from `table_name` group by `column` having 限定条件

-- 显示每个部门平均工资大于 2000 的每个岗位的薪资平均值和最低值
-- 先根据部门分组,再根据岗位分组;使用别名筛选,值只计算一次,效率高一些
select avg(salary) as avg_sal, min(salary), deptno, job 			-- salary 字段未分组,但使用了分组函数
from `table_name` 
group by deptno, job 
having avg_sal > 2000

-- 该分组查询可以执行,但结果无意义
/*
以 job 分组,但查询了 enamel、sal;这两个字段会随机显示一条记录;结果无实际意义
在 Oracle 更严格的语法规范中无法执行通过
*/
select ename, avg(sal), sal, job 
from emp 
group by job

多表查询

连接查询

多表查询需要使用连接进行查询

分类
  • 按语法出现年代
    • SQL 92
      • 一些较老的 DBA 可能还在使用
      • DBA:数据库管理员
        • Database Administrator
      • 语法
        • 多表使用 , 隔开
        • 连接条件写在 where 字句
    • SQL 99
      • 相对较新的语法
        • ...join... on...
      • 多表使用 join 连接
        • 连接条件写在 on 字句
      • 表连接条件与 where 条件分离
        • 结构更清晰
  • 按表的连接方式
    • 内连接
      • 等值连接
      • 非等值连接
      • 自连接
    • 外连接
      • 左外连接
      • 右外连接
    • 全连接:很少使用
内、外连接
  • 内连接
    • 多表使用内连接,凡是能匹配的记录全部查询出来
    • 两张表没有主副之分
  • 外连接
    • 多表外连接有主副表之分
    • 主要查询主表数据,同时查询副表数据
    • 即 主表数据全部显示,副表只显示匹配数据
      • 副表不匹配的数据显示 null
笛卡尔积

两张表同时查询

  1. 默认一张表中每一行和另一张表每一行组合并返回结果
    • 即两张表进行排列组合
    • 总记录数 = 第一张表记录数 * 第二张表记录数
  2. 默认返回的结果称为多表笛卡尔集
    • 多表查询不含过滤条件就会出现笛卡尔积现象
    • 加条件过滤以避免笛卡尔积现象,但查询次数不会减少
      • 次数 = 表记录数 * 另一张表记录数
      • 只显示有效记录

处理过滤条件限定查询结果

  • 多表查询时过滤条件不能少于表数量 - 1
    • 至少有任两张表有相关字段约束
  • select 杳询的多表公有的字段必须标明所属表
    • 例如:emp.deptno
  • 两张表之间要有相关联的列作为约束进行多表查询
    • 相同字段各自标明所属表,并以该字段为唯一列查询
      • 例如:emp.deptno = dept.deptno
    • 一张表的字段在另一张表中筛选
      • 例如:sal between losal and hisal
内连接
等值连接
  • 连接条件为等值关系
-- 语法; inner 可省略
select 字段 from A [inner] join B on 连接条件 where 限定条件
/*
SQL 99 语法,表连接条件 与 where 条件分离
*/
select name, emp.deptno, dname from emp join dept		-- 从 emp、dept 两张表中查询显示name、deptno、dname
on emp.deptno = dept.deptno								-- 对两张表中相同的字段作为连接条件进行查询

/*
SQL 92 语法,连接条件在 where 中
*/
select name, emp.deptno,dname from emp, dept
where emp.deptno = dept.deptno
非等值连接
  • 连接条件关系不是等值关系
-- 语法相同
select ... from A join B on ... where ...
-- 显示员工姓名,工资,工资级别;姓名、工资在表emp,工资级别在表salgrade
select ename, sal, grade from emp join salgrade
on sal between losal and hisal			-- 连接条件为最低工资和最高工资之间
自连接
  • 将一张表当作两张表使用

    • 需要使用表别名查询,否则无法定义字段归属
-- 同时显示员工名和对应的上级名
-- 将emp表当作两张表分别取别名a、b,同时显示两张表中的ename
select a.ename as '员工', b.ename as '上级' from emp a join emp b
on a.mgr = b.empno				-- 连接条件一张表的上级编号等于另一张表的员工编号
外连接
  • 即使筛选条件不匹配也全部显示,使用最多

    • 多表外连接有主副表之分
      • 主要查询主表数据,同时查询副表数据
      • 即主表数据全部显示,副表只显示匹配数据
        • 副表不匹配的数据显示 null
  • 主表满足条件的记录无视连接条件条件全部显示

-- 语法;outer 可省略
左表 left / right [outer] join 右表 on 连接条件
左外连接

左边表即使连接条件不匹配也全部显示

-- 左外连接,tab1表即使不满足限定条件也显示对应记录
select * from tab1 left join tab2 on 限定条件
右外连接

右边表即使连接条件不匹配也全部显示

-- 右外连接,tab2表即使不满足限定条件也显示对应记录
select * from tab1 right join tab2 on 限定条件
多表查询
  • 三张及以上表
-- A 先连接 B,连接之后 A 再连接 C 
select ... 
from A join B 
	on ... 
	join C 
	on ... 
	join ... 
where...

-- 查询每一个员工的部门名称、工资等级、上级领导
select e.ename '员工', d.dname, s.grade, e1.ename '领导' 
from emp e join dept d 
	on e.deptno = d.deptno					-- 内连接 dept 表
	join salgrade s 
	on e.sal between losal and hisal		-- 内连接 salgrade 表
	left join emp e1 
	on e.mgr = e1.empno;					-- 左连接自身

子查询

  • 嵌入在其它 sql 语句中的 select 语句,也叫嵌套子查询
  • 将一次查询的结果当作数据嵌套入另一次查询中
    • 作为 where 语句条件
    • 作为临时表数据
    • 也可嵌套在 select 字句
临时结果
  • 将子查询结果当作数据使用在 where 子句中
  • 或使用在 where 语句中
    • in() 操作符:其中一个
    • all() 操作符:满足所有
    • any() 操作符:满足任意一个
# 嵌套子查询了:跟 SIMTH 一个部门的员工,不包括SMITH
select ename from emp 
where job = (
    select job from emp where ename = 'smith'
) and ename != 'smith'

# in 操作符
-- 查询跟10号部门有相同职位的人的姓名、职位、工资、编号,不包括10号部门
select ename, job, sal, deptno from emp
where job in ( 								-- 在下列的结果之中的其中一个
	select distinct job from emp 	
    where deptno = 10 						-- 查询在10号部门的职位并去重
) and deptno != 10							-- 不包括 10 号部门
   	
# all 操作符
-- 查询所有工资大于30部门所有人工资的人姓名、工资、部门号
select ename, sal, deptno from emp
where sal > all(							-- 大于所有
	select sal from emp where deptno = 30	-- 部门编号为 30 的员工的工资
)   
-- 或者 where sal > (select max(sal) ...)   -- 大于最大值
     
# any 操作符
-- 查询所有工资大于30部门其中一人工资的人姓名、工资、部门号
select ename, sal, deptno from emp
where sal > any(							-- 大于任意一个
	select sal from emp where deptno = 30 	-- 30 号部门工资
)  
-- 或者 where sal > (select min(sal) ...)	  -- 大于最小值

# 嵌套 select 查询员工名、部门名
select ename, (select dname from dept d 
     where e.deptno = d.deptno ) 
from emp e
多列匹配
  • (deptno, job) =(select deptno, job from ...
    • 等价于 deptno = Smith.deptno and job = smith.job
    • 括号中对应位置数据匹配
-- 查询所有人中和smith的部门、职位相同的员工
select * from emp
    where (deptno, job) = ( 
    	select deptno, job from emp  
                where ename = 'smith'	-- 查询simth的职位
    ) and ename != 'smith'
临时表
  • 将子查询的结果当作临时表使用

    • 临时表中出现的列名和原表中相同的也需要表明
-- 查询ecs表中各类商品中最高价格的商品名、商品id、价格
select goods_id, ecs.cat_id,goods_name,shop_price
from( 
    select cat_id, max(shop_price) as max_price					-- 先查询ecs表中各类别商品最高价格 
    from ecs	      
    group by cat_id  										    -- 根据类别分组		
    ) temp join ecs  	-- 将查询出的结果当临时表来用,取别名 temp;和 ecs 内连接查询
on temp.cat_id = ecs.cat_id and temp.max_pricee = ecs.shop_price	-- 连接条件为 id 、价格 相等

合并查询

  • 合并多个 select 语句的结果

    • 集合操作符:union、union all
  • union all

    • 将两个结果集合并,使用时不会取消重复行
  • union

    • 将两个查询结果集取并集,重复纪录只显示一次
  • 可用于毫无相关的表拼接数据

    • 拼接时不同查询的字段数要相等
select ename from emp where job = 'MANAGER'
union all
select ename from emp where job = 'SALESMAN';

分页查询

  • 分页公式
    • limit 每页记录数 * ( 页数 - 1 ), 每页记录数
-- 语法
select ... limit start, rows
-- 从第 start + 1 行开始取,取rows行; start从 0 开始

-- 显示部门id和平均工资
select id, avg(salary) as avg_sal
from employee
where id = 20
group by id					-- 根据 id 分组
having avg_sal > 1000		-- 平均工资大大于 1000 
order by avg_sal desc		-- 各部门内根据平均工资降序
limit 0, 2 					-- 显示第一页两行记录;或 limit 2: 默认从 0 开始

sql执行顺序

执行顺序

  • from → where → group by → having → select → order by → limit

你可能感兴趣的:(mysql,mybatis,数据库)