第35次文章:数据库简单查询
- 2019 年 10 月 8 日
- 笔记
本周学习的数据库,有一种明显的感觉,语法简单,基本上不会有大段大段的代码出现,简简单单的几行代码就可以完成我们需要实现的任务,或许是因为我们的任务比较初级吧!嘻嘻!
所以本周主要分享的是一些语法结构,如果每个语法都给出一个例子的话,这篇文章将会出奇的长。所以,小白对于比较生疏的一些语法,会给出一个具体案例进行讲解,剩余比较简单的案例,各位小伙伴就自己摸索一下,很简单的哟!
遇到什么问题,想要和小白讨论的话,可以在文章下面留言,或者直接添加微信号:javaxiaobaizhushou,与小白面对面交流呀!下面进入正式的分享啦!
紧接上周的内容,补充一下常见的几款数据库管理系统:
mysql、oracle(甲骨文),db2(IBM)、sqlserver(微软)
sql 语言分类
DQL语言的学习:数据查询语言(date query language)
DML语言的学习:数据操作语言(data manipulation )
DDL语言:数据定义语言data define language
TCL语言:事务控制语言transaction control language
在下面使用到的案例中,我们都用下面的一张emp表进行查询,所以我就先把这张表截图放在这里,便于后续的查看

tips:这张表格仅仅是用作我们在后续的操作,并没有任何实际意义哈,不用纠结里面的每个值是不是符合现实逻辑。
进阶1:基础查询
一、语法
select 查询列表 from 表名;
二、特点
1、查询列表可以是字段、常量、表达式、函数,也可以是多个
2、查询结果是一个虚拟表
三、示例
1、查询单个字段
select 字段名 from 表名;
2、查询多个字段
select 字段名,字段名 from 表名;
3、查询所有的字段
select * from 表名;
4、查询常量值
select 常量值;
注意:字符型和日期型的常量值必须用单引号引起来,数值型不需要
5、查询函数
select 函数名(实参列表);
6、查询表达式
select 100/1234;
注意:可以使用正常的加减乘除,但是不能使用java中++ —
7、起别名
(1)as
(2)空格
8、去重
select distinct 字段名 from 表名;
注意:去重的时候,只能对一个字段名进行去重处理。
9、+
作用:做加法运算
select 数值+数值;直接运算
select 字符+数值;先试图将字符转换成数值,如果转换成功,则继续运算;否则将字符转换为0,再做运算。
select null+值;结果都为null
在这里我们给出一个字符串连接的案例,便于各位同学的理解吧~
/* java中的+号: (1)运算符,两个操作数都为数值型 (2)连接符,只要有一个操作数为字符型 mysql中的+号: 仅仅只有一个功能:运算符 select 100+90;两个操作数都为数值型,则做加法运算 SELECT '123'+90; 只要其中一方为字符型,试图将字符型数值转换为数值型 如果转化成功,则继续做加法运算 SELECT 'ans'+90; 如果转换失败,则将字符型数值转换为0 SELECT null+10; 只要其中一方为null,则其结果肯定为null */ #案例,查询员工名和姓连接成一个字段,并显示为 姓名,实现字符串的连接使用concat函数 SELECT CONCAT(empname, last_name) 全名 FROM emp;
结果图:

tips:mysql中的‘+’号不具备拼接字符串的特性,需要单独利用拼接字符串的函数concat(),来完成拼接功能。
10、【补充】concat函数
功能:拼接字符串
select concat(字符1,字符2,字符3,…..)
11、【补充】ifnull函数
功能:判断某字段或表达式是否为null,如果为null 返回指定的值,否则返回原本的值
select ifnull(bonus,0) from emp;
12、【补充】isnull
功能:判断某字段或表达式的值是否为null,如果是,则返回为1,如果不是,则返回为0
进阶2:条件查询
一、语法
select 查询列表 from 表名 where 筛选条件;
二、筛选条件的分类
1、简单条件运算符
> < = <>不等于 >= <= <=>安全等于
2、逻辑运算符
&& and
|| or
! not
3、模糊查询
我们着重对于模糊查询进行详细介绍,下面给出相应的案例:
(1)like:一般搭配通配符使用,可以判断字符型和数值型
通配符:%任意多个字符,_任意单个字符
/* LIKE 特点: 1.一般和通配符搭配使用 通配符: % 任意多个字符,包含0个字符 _ 任意单个字符 */ #案例1:查询员工名中带有字母a的员工 SELECT * FROM emp WHERE empname like '%a%'; #案例2:查询员工名中第三个字符为i,第五个字符为e的员工名和工资 SELECT empname,salary from emp WHERE empname LIKE '__i_e%'; #案例3:查询员工名中第二个字符为_的员工名,包含有特殊字符 SELECT empname FROM emp WHERE empname LIKE '_$_' ESCAPE '$';#可以使用任意字符与使用escape关键字一起使用,将此字符改变为转义字符;或者使用斜杠转义:empname LIKE '__'
查看一下结果图:
案例1结果:

案例2结果:

案例3结果:

tips:这里主要说明一下案例3结果,由于我们的数据集中,并没有员工名中包含有‘_’的员工。所以最后查询的结果为空,而案例3的意义在于说明对于转义字符的使用问题。我们除了使用斜杠之外,增加了一种使用escape关键字的方法。最后的结果中,并没有报语法错误,所以证明这个关键字是可以使用的。
(2)between and
#2.between and /* 1.使用between and 可以提高语句的简洁度 2.包含临界值 3.两个临界值不要调换顺序 */ #案例1.查询员工薪资在2000到5000之间的员工信息 select * FROM emp where salary>=2000 AND salary<=5000; #------------------- select * FROM emp WHERE salary between 2000 and 5000;
两个查询的结果集相同,如下所示:

tips:使用between and进行模糊查询的时候,我们需要注意两个数值之间的顺序,而且between and模糊查询最后代表的是一个范围内的结果。
(3)in
/* 含义:判断某字段的值是否属于in列表中的某一项 特点: (1)使用in提高语句的简洁度 (2)in列表的值类型必须一致或兼容 '123' 123 (3)列表中不支持通配符的使用 */ #查询:查询员工的姓名为tom1、tom、ceimeng的员工的名字和部门编号 SELECT empname,deptId FROM emp where empname = 'tom1' OR empname = 'tom' OR empname = 'ceimeng'; #------------------------------------------ SELECT empname,deptId FROM emp where empname IN('tom1','tom','ceimeng');
两个查询的结果集也相同:

tips :关键字in的模糊查询更加类似于一种列表清单,在此列表清单内的数据都会被列举出来。
(4)is null 和 is not null:用于判断null值
/* =或<>不能用于判断null值 is null 或者 is not null 可以判断null值 #is null pk <=> is null :仅仅可以判断null值,可读性较高,建议使用 <=> :既可以判断null值,又可以判断普通的数值,可读性较低 */ #案列1:查询没有奖金的员工名和奖金 SELECT empname,bonus FROM emp WHERE bonus is NULL; #---------------- #安全等于 <=> SELECT empname,bonus FROM emp WHERE bonus <=> NULL;
查看一下结果集:

tips:案例中也给出了两种判断null方法,供各位同学选择~
进阶3:排序查询
基本的语法与上面的两种相同,主要是使用order by关键字
#进阶3:排序查询 /* 引入: select * FROM emp; 语法: select 查询列表 FROM 表 【where 筛选条件】 ORDER BY 排序列表 【asc|DESC】 特点: 1、asc代表的是升序,desc代表的是降序 如果不写,默认的是升序 2、order by字句中可以支持单个字段、多个字段、表达式、函数、别名 3、order by字句一般是放在查询语句的最后面,limit字句除外 */ #案列1:查询薪资>=2000的员工信息,按生日进行排序【添加筛选调价】 SELECT * from emp where salary >= 2000 ORDER BY birthday DESC; #案列2:按年薪的高低显示员工的信息和 年薪【按表达式排序】 SELECT *,salary+IFNULL(bonus,0) '年薪' FROM emp ORDER BY salary+IFNULL(bonus,0) DESC; #案例3:查询员工信息,要求先按照薪资升序,再按照员工编号降序【按多个字段进行排列】 SELECT * FROM emp ORDER BY salary ASC,id DESC;
在上面给出了3个案例,最后的结果如下所示:
案例1:

案例2:

案例3:

tips:上面的三个案例基本涵盖了我们经常使用到的几种排序情况,通过总结,我们可以发现,order by子句的使用方法与select子句的使用方法基本一致,主要差别在于使用的位置在整个语句的后面。
进阶4:常见函数
一、基本概念
类似于java的方法,将一组逻辑语句封装在方法体中,对外暴露方法名。
好处:
1、隐藏了实现细节
2、提高代码的重用型调用:select 函数名(实参列表)【from 表】;
特点:
1、叫什么(函数名)
2、干什么(函数功能)
分类:
1、单行函数 如 CONCAT、length、ifnull
2、分组函数 功能:做统计使用、聚合函数、组函数
二、单行函数
(1)字符函数
length:计算字符串长度
concat:拼接字符串
substr:截取从指定索引后面所有字符,或者,截取从指定索引处,指定字符长度的字符。注意:索引是从1开始的。
instr:返回子串第一次出现的索引,如果找不到返回0。
trim:去除子串前后的空格
upper、lower:将所有的字符串全部转换为大写或者小写
lpad、rpad:用指定的字符实现左(或右)填充指定长度
replace :替换指定的字符串
(2)数学函数
round:四舍五入,可以指定保留小数点后面多少位
ceil:向上取整,返回>=改参数的最小整数
floor:向下取整,返回<=该参数的最大整数
truncate:从小数点后面第几位开始截断
mod:取余函数
对于取余函数我们需要注意一下其内部的计算法则,以避免在负数取余的时候犯错。
/* 取余函数的底层运算 mod(a,b) : a-a/b*b MOD(-10,-3) :-10-(-10)/(-3)*(-3)=-10-3*(-3)=-1 */ select MOD(-10,-3); SELECT -10%(-3);
tips:正因为上述的取余运算的底层法则,使得负数取余的时候,余数依旧为负数。
(3)日期函数
NOW:显示当前年月日时分秒
curdate:仅仅显示当前的日期
curtime:仅仅显示当前的时间
year、month、day、hour、minute、second:分别显示相应的时间单位
str_to_date:将时间字符串通过指定的格式转换为日期
date_format:将时间按照指定的格式转化为字符串
(4)控制函数
if函数
#1.if函数:if else 的效果 SELECT empname,bonus, IF(bonus is NULL,'没奖金,呵呵','有奖金,嘻嘻') 备注 FROM emp;
我们查看一下结果集:

tips:通过上面的结果集,我们可以明显的看出,if函数类似于java中的三位运算符,当判断条件为真时,输出第一个结果,条件为假时,输出第二个结果。
case函数
#2.case函数的使用一:switch case 的效果 /* java 中 switch(变量或表达式){ case 常量1:语句1;break; ..... DEFAULT:语句n;break; } mysql 中 case 要判断的字段或表达式 when 常量1 then 要显示的值1或语句1; when 常量2 then 要显示的值2或语句2; ... ELSE 要显示的值n或语句n; END */ /*案例:查询员工的工资,要求 部门号=1,显示的工资为1.1倍 部门号=2,显示的工资为1.2倍 部门号=3,显示的工资为1.3倍 部门号=4,显示的工资为1.4倍 */ SELECT empname,salary 原始工资,deptId, CASE deptId WHEN 1 THEN salary*1.1 WHEN 2 THEN salary*1.2 WHEN 3 THEN salary*1.3 ELSE salary*1.4 END 新工资 FROM emp; #3.CASE 函数的使用二:类似于 多重if /* java中: if(条件1){ 语句1; }else if(条件2){ 语句2; } ... ELSE{ 语句n; } mysql 中: CASE WHEN 条件1 THEN 要显示的值1或语句1; WHEN 条件2 THEN 要显示的值2或语句2; ..... ELSE 要显示的值n或语句n; end */ #案例:查询员工的工资情况 /* 如果工资>10000,显示的A级别 如果工资>5000,显示的B级别 如果工资>1000,显示的C级别 否则,显示的D级别 */ SELECT empname,salary, CASE WHEN salary>10000 THEN 'A' WHEN salary>5000 THEN 'B' WHEN salary>1000 THEN 'C' ELSE 'D' END 工资等级 FROM emp;
用法一的结果:

用法二的结果:

tips:对于两种case的用法,全部都已经展示在了代码行中,各位同学自己查看即可哈!
三、分组函数
(1)基本功能
功能:用作统计使用,又称为聚合函数或统计函数或组函数。
(2)分类
sum 求和、avg 平均值、max 最大值、min 最小值、count 计算个数
下面对这几个函数进行简单的介绍
/* 特点: 1、sum avg 一般用于处理数值型 max min count 可以处理任何类型 2、以上分组函数都忽略null值 3、可以和关键字distinct搭配使用,实现去重的运算 4、count函数的单独介绍 一般使用count(*)用作统计行数 5、和分组函数一同查询的字段要求是group by 后的字段 */ #1、和distinct搭配 SELECT COUNT(DISTINCT deptId) from emp; #2、count函数的详细介绍 SELECT COUNT(*) from emp;#统计整张表中的所有行数,也可以通过在添加常量的方法来统计:SELECT COUNT(1) from emp; #效率: #MYISAM 存储引擎下 , count(*)的效率高 #INNODB 存储引擎下 , count(*)和COUNT(1)的效率差不多,比count(字段)要高一些
案例1结果图:

案例2结果图:

tips:通过案例1,我们主要说明一下去重关键字与统计函数的搭配使用。在对deptId进行计数的时候,可以计算有多少个部门id。
进阶5:分组查询
一、基本思想
在前面的进阶过程中,我们一直是针对整张表格的数据进行。分组查询主要是根据用户的需求,对自己设定的类别进行单独的统计计算。在分组查询中主要使用group by关键字。
二、语法
SELECT 分组函数,列(要求出现在group by的后面)
FROM 表 【where 筛选条件】
GROUP BY 分组的列表
【order by 子句】
注意点:查询列表必须特殊,要求是分组函数和group by 后出现的字段
三、特点
#进阶5:分组查询 /* 特点: 1、分组查询中的筛选条件分为两类 数据源 位置 关键字 分组前筛选 原始表 GROUP BY子句的前面 WHERE 分组后筛选 分组后的结果集 GROUP BY子句的后面 HAVING (1)分组函数做条件肯定是放在having子句中 (2)能用分组前筛选的,就优先考虑使用分组前筛选 2、group by子句支持单个字段分组,多个字段分组(多个字段之间用逗号隔开,没有顺序要求),表达式(使用的较少) 3、也可以添加排序(排序放在整个分组查询的最后) */ #案例1:查询每个部门的平均工资 SELECT round(avg(salary),2),deptId FROM emp GROUP BY deptId; #添加分组后复杂的筛选条件 #案例2:查询部门编号>1的每个部门中,最低工资大于1000的部门编号是哪个,以及其部门的最低工资 SELECT deptId,MIN(salary) 部门最低工资 FROM emp WHERE deptId>1 GROUP BY deptId HAVING 部门最低工资>5000;
案例1结果:

案例2结果:

tips:
案例2中,首先要求部门编号大于1,这个筛选条件我们可以直接在原始表中进行,所以使用的是where关键字,得到了第一步筛选之后的表格——部门编号大于1的各个部门的最低工资。
但是根据案例中的要求,每个部门的最低工资需要大于1000,这个筛选是基于我们第一次筛选之后表格进行的,所以此时我们不能够继续使用where关键字,需要使用having关键字,表示我们对第一次筛选得到的表格进行第二次筛选。同时根据我们的代码也可以发现,在使用having关键字的时候,我们还可以使用别名进行二次筛选。