ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

MySQL_查询汇总(一)

2022-04-28 00:04:36  阅读:261  来源: 互联网

标签:ename sal -- 汇总 查询 emp MySQL select


一、MySQL常用命令

完整看完就能掌握MySQL中大部分的查询问题了

-- 查看所有数据库
show databases;

-- 选择使用哪个数据库
use <数据库名>;

-- 创建数据库
create database <数据库名>;

-- 查看所有数据表。(前提是要先选择使用哪个数据库)
show tables;

-- 查看表结构
desc <表名>;

-- 导入数据(*.sql文件)注意路径中不要有中文
source <.sql文件路径>

-- 查看MySQL版本号
select version();

-- 查看正在使用的数据库。
select database();

-- 中止sql语句的输入
\c

-- 退出MySQL
exit;

二、SQL分类

DQL:数据库查询语言

凡是带有select关键字的都是查询语句。

select 查

DML:数据库操作语言

凡是对表当中的数据进行增删改的都是DML。

insert 增

delete 删

update 改

DDL:数据定义语言

凡是带有create、drop、alter的都是DDL。DDL主要操作的是表的结构,不是表中的数据。

create 新建

drop 删除

alter 修改

TCL:事务控制语言

事务提交:commit

事务回滚:rollback

DCL:数据控制语言

授权:grant

撤销权限:revoke

三、查询语句

1.简单查询

selectfrom 都是关键字,字段名表名 都是标识符。

对于SQL语句来说,是通用的。所有的SQL语句都以“;”结尾。SQL语句不区分大小写。

a>查询一个字段

select <字段名> from <表名>;

b>查询两个或多个字段

字段之间用“,”隔开。

select <字段名>,<字段名>,... from <表名>;

c>查询所有字段

  1. 可以把每个字段都写上。
  2. 可以使用“*”,代表全部。

在Java程序中不要写 "*" 号,因为它会先把星号转换为字段,这个过程也会占用一定的时间,所以效率比较低且可读性较差。

select * from <表名>;

d>给查询的列起别名

使用 as 关键字起别名。as 关键字可以省略。

注意:只是将显示的查询结果列名显示为别名,原表列名不变。记住:select语句是永远不会进行修改操作的。(只负责查询)

select deptno,dname as deptname from dept;
-- 或
select deptno,dname deptname from dept;

问:假设起别名的时候,别名里面想要加空格,怎么办?————用 单引号 将别名括起来。

select deptno,dname 'dept name' from dept;

2.列参和数学运算

-- 列可以参与运算
select ename, sal*12 from emp;
-- 也可以起别名,别名是中文就用单引号括起来
select ename, sal*12 as yearsal from emp;

3.条件查询

对表中数据进行条件筛选,将符合条件的数据取出来。

-- 语法格式
select <字段名> from <表名> where <条件>;
符号 含义
= 等于
<> 或 != 不等于
< 小于
<= 小于等于
> 大于
>= 大于等于
between ... and ... 两个值之间,等同于 >= and <=
is null 为空
is not null 不为空
and 并且
or 或者
in 包含
not 取非,主要用在 is 或 in 中
like 模糊查询(% 匹配任意个字符,_ 一个下划线只匹配一个字符)
-- 查询工资等于800的数据
select empno, ename from emp where sql = 800;
-- 查询工资不等于800的数据
select empno, ename from emp where sql != 800;
-- 查询补助为null的数据(需要用is,不能用=)
select empno, ename sal, comm from emp where comm is null;
-- 查询工作岗位是manager和salesman的员工(in后面不是一个区间,而是具体的值)
select empno, ename, job from emp where job in ('manager', 'salesman');
-- 找出名字中含有“O”的
select ename from emp where ename like '%O%';
-- 找出名字中以“T”结尾的
select ename from emp where ename like '%T';
-- 找出名字中第二个字母是“A”的
select ename from emp where ename like '_A%';

4.排序

a>单个字段排序

-- 正序排序(从小到大排序)。加不加asc都行,因为默认是升序。
select * from car_information order by car_price (asc);
-- 倒序排序(从大到小排序)
select * from car_information order by car_price desc;

b>多个字段排序

查询所有车辆,要求按照车辆价格升序,如果价格一样的话,再按照品牌升序排序。

-- car_price在前,起主导作用。只有当car_price相等的时候,才会考虑car_brand。
select * from car_information order by car_price, car_brand;

5.综合案例

找出价格在5到10的车辆信息,要求按照价格降序排列。

select
	car_brand, car_price
from
	car_information
where
	car_price between 5 and 10
order by
	car_price desc;

四、数据处理函数

数据处理函数又被称为单行处理函数,对数据是一行一行处理的。

特点:一个输入对应一个输出

函数 含义
lower 转换小写
upper 转换大写
substr 取子串 substr(被截取的字符串,起始下标,截取的长度)
length 取长度
trim 去空格
str_to_date 将字符串转换成日期
date_format 格式化日期
format 设置千分位
round 四舍五入
rand() 生成随机数
lfnull 可以将null抓换为一个具体值
-- 例:转换小写
select lower(ename) as ename from emp;

五、分组函数

分组函数又被称为多行处理函数。

特点:输入多行,最终输出一行。

注意:分组函数在使用的时候必须先进行分组,然后才能用。如果没有对数据进行分组,默认整张表为一组。

函数 含义
count 计数
sum 求和
avg 平均值
max 最大值
min 最小值
-- 找出最高工资
select max(sal) from emp;
-- 找出最低工资
select min(sal) from emp;
-- 计算工资和
select sum(sal) from emp;
-- 计算平均工资
select avg(sal) from emp;
-- 计算员工数量
select count(ename) from emp;

分组函数需要注意的点

  1. 分组函数自动忽略null,你不需要对null进行处理。(null不是一个值,是什么也没有)

  2. 分组函数中的count(*)和count(具体字段)的区别:

    count(*):统计表当中的总行数。(因为数据表中不存在全部字段都为null的数据)

    count(具体字段):表示统计该字段下所有不为null的元素的总和。

  3. 分组函数不能直接使用在where子句中。

    例:找出比最低工资高的员工信息。

    select ename, sal from emp where sal > min(sal);
    

    表面上看没问题,但是运行报错:错误使用分组函数。

    看完 《分组查询》 才能明白。

  4. 所有的分组函数可以组合起来一起用。

    select sum(sal), min(sal), max(sal), avg(sal), count(*) from emp;
    

六、分组查询(⭐⭐⭐⭐⭐)

在实际的应用中,可能有这样的需求,需要先进行分组,然后对每一组的数据进行操作。

这时候就需要用到分组查询了

select
	...
from
	...
group by
	...

例:

​ 计算每个部门的工资和?

​ 计算每个工作岗位的平均薪资?

​ 找出每个工作岗位的最高薪资?

关键字执行顺序

将之前的关键字全部组合在一起,来看一下他们的执行顺序:

select
	...
from
	...
where
	...
group by
	...
order by
	...

顺序不能改变!!!

执行顺序是什么:

  1. from
  2. where
  3. group by
  4. select
  5. order by

一个大问题

为什么分组函数不能直接使用在where后面?

-- 报错
select ename, sal from emp where sal > min(sal);

-- 成功
select sum(sal) from emp;

原因是:执行顺序。分组函数在使用的时候必须先进行分组,然后才能用。

从语法层面上看,where 的执行在 group by 前面,而 select 的执行在 group by 后面,select 的时候,group by 已经执行结束了。(group by没写不等于没有,没写表示整张表分为一组)

案例分析1

  1. 找出每个岗位的工资和。

    select
    	job, sum(sal)
    from
    	emp
    group by
    	job;
    

    以上这个语句的执行顺序:

    1. 先从 emp 表中查询。
    2. 根据 job 字段进行分组
    3. 然后对每一组的数据进行 sum(sal)

a>提问:

下面的语句能否执行:

select ename, job, sum(sal) from emp group by job;

答:以上语句在MySQL中可以执行,但没有意义。sum(sal)按照job只能分出5组,可是ename有14个数据,ename对应不了sum(sal)。

在MySQL中可以执行,但是在Oracle中会报错。Oracle的语法比MySQL严格。

重要结论:

在一条select语句当中,如果有group by语句的话,select后面只能跟:参加分组的字段、以及分组函数。其他的一律不能跟。

案例分析2

找出”每个部门,不同工作岗位“的最高薪资。

技巧:两个字段联合成一个字段看。(两个字段联合分组)

select
	deptno, job, max(sal)
from
	emp
group by
	deptno, job;

having子句

having可以对分完组之后的数据进一步过滤。

having 不能单独使用,having 不能代替 wherehaving 必须和 group by 联合使用。

案例分析

找出每个部门最高薪资,要求显示最高薪资大于3000的。

  1. 找出每个部门最高薪资

    按照部门编号分组,求每一组最大值。

    select deptno, max(sal) from emp group by deptno;
    
  2. 要求显示最高薪资大于3000的

    这题不能使用where,因为where的执行顺序在group by前面,所以只能使用having来过滤。

    select 
    	deptno, max(sal)
    from
    	emp
    group by
    	deptno
    having
    	max(sal) > 3000;
    

思考一个小问题

以上的sql语句执行效率是不是低?

答:是的,比较低,实际上可以这样考虑:先将大于3000的都找出来,然后再分组。

select
	deptno, max(sal)
from
	emp
where
	sal > 3000
group by
	deptno;

优化策略:

能够使用 where 过滤的,都尽量使用 where

wherehaving 优先选择 where

大总结

-- 关键字只能按照这个顺序来,不能颠倒
select
	...
from
	...
where
	...
group by
	...
having
	...
order by
	...

执行顺序:

  1. from
  2. where
  3. group by
  4. having
  5. select
  6. order by

最终案例

找出每个岗位的平均薪资,要求显示平均薪资大于1500的,除manager岗位之外,要求按照平均薪资降序排列。

select
	job, avg(sal) as avgsal
from
	emp
where
	job != 'manager'
group by
	job
having
	avg(sal) > 1500
order by
	avgsal desc;

七、查询结果去重

把查询结果去除重复记录,原表数据不会被修改,只是查询结果去重。

需要使用一个关键字:distinct

select distinct job from emp;


-- 这样编写是错误的,语法错误。distinct只能出现在所有字段的最前方。
select ename, distinct job from emp;

-- distinct出现在job和deptno两个字段之前,表示两个字段联合起来去重。
select distinct job, deptno from emp;

案例分析

统计一下工作岗位的数量?

select count(distinct job) from emp;

八、连接查询(⭐⭐⭐⭐⭐)

什么是连接查询:

从一张表中单独查询,称为单表查询。

从emp表和dept表联合起来查询数据,从emp表中取员工姓名,从dept表中取部门名字。这种跨表查询,多张表联合起来查询数据,叫做连接查询。

连接查询的分类:

根据语法的年代分类:

  • SQL92:1992年的时候出现的语法(几乎废了)
  • SQL99:1999年的时候出现的语法

根据表连接的方式分类:

  • 内连接:
    • 等值连接
    • 非等值连接
    • 自连接
  • 外连接:
    • 左外连接(左连接)
    • 右外连接(右连接)
  • 全连接(很少使用)

笛卡尔积现象(连接查询底层)

查询每个员工所在部门名称?

image-20220427234149864

  1. 当两张表进行连接查询时,没有任何条件的限制会发生什么?

    select ename, dname from emp, dept;
    

    56 rows in set (0.00 sec)

    当两张表进行连接查询,没有任何条件限制的时候,最终查询结果条数是两张表条数的乘积,这种现象被称为:笛卡尔积现象

    怎么避免笛卡尔积现象呢?

    连接时加条件,满足这个条件的记录被筛选出来

    select
    	ename, dname
    from
    	emp, dept
    where
    	emp.deptno = dept.deptno;
    ================================
    -- 可以使用别名
    -- 为什么select里可以使用from里起的别名,因为select的执行顺序在from之后。
    select
    	e.ename, d.dname
    from
    	emp e, dept d
    where
    	e.deptno = d.deptno;
    

    思考:最终查询的结果条数是14条,但是匹配的过程中,匹配的次数减少了吗?
    答:没有,还是56次,只不过进行了四选一。匹配次数没有减少。

    表连接越多,效率就越低。因为笛卡尔积现象,匹配次数会很多。

内连接

内连接的特点:完成能够匹配上这个条件的数据查询出来。

等值连接

案例:查询每个员工所在部门名称,显示员工名和部门名?(使用SQL99语法

-- 92语法
select
	e.ename, d.dname
from
	emp e, dept d
where
	e.deptno = d.deptno;

-- SQL92的缺点:结构不清晰,表的连接条件和后期进一步筛选的条件,都放在了where后面。 

===========================

-- 99语法,inner join = join
select
	e.ename, d.dname
from
	emp e
(inner) join
	dept d
on
	e.deptno = d.deptno;	-- 条件是等量关系,所以被称为等值连接。
	
-- SQL99的优点:表连接的条件是独立的,连接之后,如果还需要进一步筛选,再往后继续添加where条件。

条件是等量关系,所以被称为等值连接。

非等值连接

案例:找出每个员工的薪资等级,要求显示员工名、薪资、薪资等级。

select
	e.ename,e.sal,s.grade
from
	emp e
inner join
	salgrade s
on
	e.sal between s.losal and s.hisal;

条件不是一个等量关系,称为非等值连接。

自连接

案例:查询员工的上级领导,要求显示员工名和对应的领导名。

select 
	e.empno,e.ename,ee.ename mgrName
from
	emp e
inner join
	emp ee
on 
	e.mgr = ee.empno;

一张表看作两张表

外连接

右外连接

案例:显示员工和部门的关系

-- 内连接
select
	e.ename, d.dname
from
	emp e
join
	dept d
on 
	e.deptno = d.deptno;
===================================
-- 右外连接
select
	e.ename, d.dname
from
	emp e
right (outer) join
	dept d
on 
	e.deptno = d.deptno;

image-20220427210323869

right表示什么:表示将join关键字右边的这张表看成是主表,然后去左边的表中查询匹配项。(left同理)

内连接是把所有能够匹配上的数据查询出来,而外连接会把主表中所有数据都查询出来,无论是否有匹配项。

思考:外连接的查询结果条数一定是 >= 内连接的查询结果条数?

​ 答:正确!

案例:查询每个员工的上级领导,要求显示所有员工的名字和领导名字

select 
	a.ename '员工名',b.ename '领导名'
from 
	emp a
left outer join
	emp b
on
	a.mgr = b.empno;

多表连接

语法:

select
	...
from
	a
join
	b
on
	a和b的连接条件
left join
	c
on
	a和c的连接条件
...

一条sql语句中,内连接和外连接可以混合。都可以出现。

案例:找出每个员工的部门名称以及薪资等级,要求显示员工名、部门名、薪资、薪资等级。

select
	e.ename '员工名',d.dname '部门名',e.sal '薪资', s.grade '薪资等级'
from 
	emp e
join
	dept d
on
	e.deptno = d.deptno
join
	salgrade s
on
	e.sal between s.losal and s.hisal;

案例:找出每个员工的部门名称以及薪资等级,要求显示员工名、领导名、部门名、薪资、薪资等级。

select
	e.ename '员工名',ee.ename '领导名',d.dname '部门名',e.sal '薪资', s.grade '薪资等级'
from 
	emp e
join
	dept d
on
	e.deptno = d.deptno
join
	salgrade s
on
	e.sal between s.losal and s.hisal
left join
	emp ee
on
	e.mgr = ee.empno;

九、子查询

什么是子查询?

​ select语句中嵌套select语句,被嵌套的select语句称为子查询。

子查询都可以出现在哪里

select 
	..(select).
from
	..(select).
where
	..(select).

where中的子查询

案例:找出比最低工资高的员工姓名和工资?

  1. 查出最低工资是多少?

    -- 第一步:查出最低工资是多少?
    select min(sal) from emp;
    

    --> 800

  2. 找出工资 >800 的

    -- 第二步:找出 >800(第一步求出的最低工资)的
    select 
    	ename,sal 
    from 
    	emp 
    where 
    	sal > 800;
    
  3. 合并

    -- 第三步:合并
    select 
    	ename, sal
    from
    	emp
    group by
    	empno
    having
    	sal > (select min(sal) from emp);
    

from中的子查询

注意:from后面的子查询,可以将子查询的查询结果当作一张临时表。

案例:找出每个岗位的平均工资的薪资等级。

  1. 计算每个岗位的平均工资。

    select job, avg(sal) `avg` from emp group by job;
    

    --> 将结果看作一张真实存在的临时表 t。
    image-20220427234241167

  2. 计算薪资等级,将t表和salgrade表进行连接,并且需要把子查询的结果起个别名。

    select
    	a.job, b.grade
    from
    	(select job, avg(sal) `avg` from emp group by job) a
    left join
    	salgrade b
    on
    	a.avg between losal and hisal;
    

select后的子查询

脱裤子放屁的感觉。可以用连接来实现。

十、union合并查询结果集

案例:查询工作岗位是MANAGER或SALESMAN的员工。

select * from emp where job = 'MANAGER' or job = 'SALESMAN';
-- 或
select * from emp where job in ('MANAGER','SALESMAN');

union:

select * from emp where job = 'MANAGER'
union
select * from emp where job = 'SALESMAN';

union的效率要高一些。对于表连接来说,每连接一次新表,匹配的次数满足笛卡尔积,成倍的翻。。。
但是union可以减少匹配的次数。在减少匹配次数的情况下,还可以完成两个结果集的拼接。

a 连接 b 连接 c

a:10条

b:10条

c:10条

匹配的次数就是:10 * 10 * 10 = 1000

a 连接 b 一个结果:10 * 10 = 100

b 连接 c 一个结果:10 * 10 = 100

使用union的话是:100 + 100 = 200 次 (把乘法变成了加法)

十一、limit(⭐⭐⭐⭐⭐)

limit是将查询结果集的一部分取出来,通常使用在分页查询中。

百度默认:一页显示10条记录
分页的作用是为了提高用户的体验,因为一次全部都查出来,用户体验差。可以一页一页翻页看。

案例:按照薪资降序,取出排名在前5名的员工。

select
	ename,sal
from 
	emp
order by
	sal desc
limit 
	0,5;

完整用法:limit startIndex,length
startIndex是起始下标,length是长度
缺省用法:limit length
length是长度,取前几条。

案例:取出工资排在[5-9]名的员工。

select
	ename, sal
from
	emp
order by
	sal desc
limit
	4,5;

分页

每页显示3条记录:
第1页:limit 0,3 [0 1 2]
第1页:limit 0,3 [3 4 5]
第1页:limit 0,3 [6 7 8]
第1页:limit 0,3 [9 10 11]

每页显示pageSize条记录:
第pageNo页:limit (pageNo-1)*pageSize,pageSize

再次总结执行顺序

  1. from
  2. where
  3. group by
  4. having
  5. select
  6. order by
  7. limit

标签:ename,sal,--,汇总,查询,emp,MySQL,select
来源: https://www.cnblogs.com/Kled/p/16201168.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有