一些盲点.
数据库中仅有月薪字段(month_salary),要求查询所有员工的年薪,并以年薪(year_salary)输出:
分析:
- 查询操作中,字段可以参与数学运算
- as 起别名,但实际上可以省略
#以下两句效果完全一致
select month_salary as year_salary from emp
select month_salary year_salary from emp
. 条件查询
#条件查询的语法
select
...
from
...
where 过滤条件;
带有
除了数学符号外,常见的条件
| between...and... | 等同于 >= and <= |
| is null | 为空 |
| is not null | 不为空 | | |
| in | 在指定的值当中 |
| not in | 不在指定的值当中 |
| exists | |
| not exists | |
| like | 模糊查询 |
in 和 or 的效率
我们知道, in的执行原理实际上是采用 = 和 or 的方式,
job in(‘MANAGER’,‘SALESMAN’,‘CLERK’)
等同于
job = ‘MANAGER’ or job = ‘SALESMAN’ or job = ‘CLERK’
sal in(1600, 3000, 5000)
等同于
sal = 1600 or sal = 3000 or sal = 5000
查询的列如果有索引或者主键,那么二者效率基本相当
否则
or的效率为O(n),而in的效率为O(log n), 当n越大的时候效率相差越明显(也就是说数据量越大的时候,in的效率越高)。
.1 and 和 or 优先级问题
找出薪资小于1500,并且部门编号是20或30的员工姓名、薪资、部门编号。
直接给出错误 SQL:
select
ename,sal,deptno
from
emp
where
sal < 1500 and deptno = 20 or deptno = 30;
结果是错的,有两个部门 30 且工资超过 1500 的也被查询了
分析:
- MS 中,and 的优先级大于 or
# 我们想要的执行顺序是 sal < 1500 and (deptno = 20 or deptno = 30)
# 实际的执行顺序是 (sal < 1500 and deptno = 20) or deptno = 30;
# 即系统先筛选出同时满足工资小于 1500 且部门 20 的人,再加上所有部分 30 的人后一起输出
sal < 1500 and deptno = 20 or deptno = 30;
# 由于 and 优先级高,系统先执行所有 and,因此执行顺序是(条件1 and 条件2)or(条件3 and 条件4 )
where 条件1 and 条件2 or 条件3 and 条件4
- 不用记忆优先级。遇到不确定的优先级时,用小括号来保证正确。
sal < 1500 and (deptno = 20 or deptno = 30)
模糊查询
模糊查询的语法格式如下:
select .. from .. where 字段 like '通配符表达式';
通配表达式也很简单,主要是
- % 代表任意多个字符。
- 下划线 “_” 代表任意一个字符。
order by排序
order by 关键字默认采用 asc 升序
#按照 sal 升序排列,如果 sal 相同的,再按照 ename 升序排列。
select empno,ename,sal from emp order by sal asc, ename asc;
distinct 去重
- distinct只能出现在所有字段的最前面。
- 且当distinct出现后,后面多个字段一定是联合去重的: 即将多个字段视为一个整体,允许部分重复,不允许整体重复。
数据处理函数
字符串处理相关之 upper/ucase、lower/lcase
# 查询所有员工名字,以大写形式展现
select upper(ename) as ename from emp;
#数据库是否对大小写敏感主要取决于操作系统.win 内不敏感,linux 内敏感
#若在 linux 内部署数据库,并且此时不知道表中的人名是大写、小写还是大小写混合,
#不妨直接将 ename 一整列都转大写,然后再用大写的人名去匹配,这样,只要确实存在这个人,不管大小写都能匹配出来
select ename, job, sal from emp where upper(ename) = 'SMITH';
字符串处理相关之 截取字符串substr
语法:substr(‘被截取的字符串’, 起始下标, 截取长度)
有两种写法:
第一种:substr(‘被截取的字符串’, 起始下标, 截取长度)
第二种:substr(‘被截取的字符串’, 起始下标),当第三个参数“截取长度”缺失时,截取到字符串末尾
注意:起始下标从1开始,不是从0开始。(1表示从左侧开始的第一个位置,-1表示从右侧开始的第一个位置。)
练习:找出员工名字中第二个字母是A的
select ename from emp where substr(ename, 2, 1) = 'A';
字符串处理相关之 concat 函数拼接字符串
语法:concat('字符串1', '字符串2', '字符串3'....)
字符串处理相关之 trim 字符串剪裁函数
### trim 函数默认体同时去除字符串前后空白
### 最终结果为 abcdef
select concat(trim(' abc '), 'def');
### 当然也可以指定仅去除前缀/后缀
###最终结果为 '111 '
select trim(leading ' ' from ' 111 ');
###最终结果为 ' 111'
select trim(trailing ' ' from ' 111 ');
###最终结尾为 '111'
select trim(both ' ' from ' 111 ')
###也可以指定去除的内容
###最终结果为 '000111'
select trim(trailing '0' from '000111000');
数字相关之 rand 生成随机浮点数
rand()生成0到1的随机浮点数。
rand(x)生成0到1的随机浮点数,通过指定整数x来确定每次获取到相同的浮点值。
数字相关之 round 四舍五入
### 对 x 进行四舍五入,只保留整数位
round(x)
### 对 x 进行四舍五入,保留 y 位小数
round(x,y)
数字相关之 ceil与floor 返回整数
- ceil函数:返回大于或等于数值x的最小整数
- floor函数:返回小于或等于数值x的最大整数
数字相关之 ifnull 空处理函数
- 在SQL语句中,凡是有NULL参与的数学运算,最终的计算结果都是NULL:
#当x为NULL时,将x当做y处理;当x不为null时,不做任何处理。
ifnull(x, y)
需求:查询每个员工的年薪。(年薪 = (月薪 + 津贴) * 12个月。注意:有的员工津贴comm是NULL。)
分析,某些行的 comm 可能是 null ,而 null 与数字做任何数学运算都得到 null
#
select (month_salary + ifnull(comm,0)) * 12 as year_salary from emp
日期相关之 获取当前日期、时间
#获取执行select语句的时间 + 日期。
now()
#获取执行sysdate()函数的时间 + 日期。
sysdate()
日期之 date_format 日期格式化字符串化
- 在 MS 中,默认的日期格式是:%Y-%m-%d %H:%i:%s,
- 直接输出日期数据的时候,日期数据会自动转换成字符串输出:
date_format 将日期转换成具有某种格式的日期字符串,通常用在查询操作当中。(date类型转换成char类型)
语法格式:
date_format(日期, '日期格式')
该函数有两个参数:
- 第一个参数:日期。这个参数就是即将要被格式化的日期。类型是date类型。
- 第二个参数:指定要格式化的格式字符串。
- %Y:四位年份
- %y:两位年份
- %m:月份(1…12)
- %d:日(1…30)
- %H:小时(0…23)
- %i:分(0…59)
- %s:秒(0…59)
需求:获取系统日期和时间,并转为这个格式展示:2000-10-11 20-15-30
日期之 str_to_date 字符串转日期
str_to_date 将 char 类型的日期字符串转换成日期类型 date,通常使用在插入和修改操作当中。(char类型转换成date类型)
str_to_date('日期字符串','指定解析模式')
需求:为一个生日字段 birth 插入数据
首先,如果提供的日期字符串格式能够被mysql解析,str_to_date函数是可以省略的,底层会自动调用该函数进行类型转换:
但如果并非指定格式,那么直接插入显然是不行的,这里采用月、日、年的格式,MS 无法解析
用 str_to_date 函数指定解析模式为 月/日/年
再例如:
日期之 时间差函数
datediff函数
计算两个日期之间所差天数:
timediff函数
计算两个日期所差时间,例如日期1和日期2所差10:20:30,表示差10小时20分钟30秒。
条件判断函数 if
#IF() 的返回值为数字值或字符串值,具体情况视其所在语境而定。
#如果 expr1 是TRUE ,则 IF()的返回值为expr2; 否则返回值则为 expr3。
IF(expr1,expr2,expr3)
#如果 sex 为1,返回字符串 '男'
select name,if(sex = 0,'男','女')
#如果工资大于3000,返回数字1
select *,if(month_salary > 3000,1,0) as High_Paid from user;
条件判断语句 case when
可以继续细分为 简单 CASE 函数 和 CASE 搜索函数
- 简单 case 函数和 if 往往能起到相同的作用
- 在 SELECT 语句中,简单 CASE 函数仅检查是否相等,而不进行其它比较。
#简单 case 函数语法格式
CASE input_expression
WHEN when_expression THEN
result_expression [...n ] [
ELSE
else_result_expression
END
#查询 sex 字段,如果是 0 则返回 '男'
SELECT CASE sex
WHEN 0 THEN '男'
WHEN 1 THEN '女'
ELSE '未知'
END
as ages
CASE 搜索函数:
- 在 SELECT 语句中,CASE 搜索函数允许根据比较值在结果集内对值进行替换。
#CASE 搜索函数语法格式:
CASE
WHEN Boolean_expression THEN
result_expression [...n ] [
ELSE
else_result_expression
#对 parent_id 一列的所有查询数据进行替换,若原本小于3,则输出 '<3',而不是输出具体数值
SELECT
CASE
WHEN parent_id < 3 THEN
'<3'
WHEN parent_id >= 3
AND parent_id < 5 THEN
'>=3 && <5'
ELSE
'>=5'
END AS parent_id_new ,
parent_id ,
type_id ,
type_name
FROM
tdb_goods_type
数据类型转换函数 cast
cast函数用于将值从一种数据类型转换为表达式中指定的另一种数据类型
#语法:
cast(值 as 数据类型)
#将字符串'2020-10-11'转换成日期date类型。
cast('2020-10-11' as date)
分组查询 group by、having
groupt by 按照某个字段分组,或者按照某些字段联合分组。
- 执行的顺序是 where --> group by --> having
- 越早过滤效率越高。因此,尽量在where中过滤,实在不行,再使用having。
- 存在 group by 关键字时,select 后面只能跟分组函数或参加分组的字段
// 报错,仅 deptno 参与了分组,而 select 后出现了 ename
select ename,deptno,avg(sal) from emp group by deptno;
having 写在group by的后面,当你对分组之后的数据不满意,可以继续通过having对分组之后的数据进行过滤。
#找出除20部分之外,其它部门的平均薪资。
#以下两句效果完全一致,但推荐第一句,尽量在 where 中过滤
select deptno,avg(month_salary) from emp where deptno != 20 group by deptno
select deptno,avg(sal) from emp group by deptno having deptno <> 20;
#查询每个部门平均薪资,找出平均薪资高于2000的部分
#这里必须要用 having 了,因为必须要找的是平均薪资大于 2000 的部分,而计算部门的平均薪资,首先要分组
select deptno,avg(month_salary) from emp group by deptno having avg(month_salary) > 2000
分组函数
SELECT colum,group_function(colum)
FROM table
[WHERE conditoin]
[GROUP BY group_by_expression]
[ORDER BY column]
- 没有 group by 关键字进行分组时也能使用分组函数
- 使用了 group by 关键字进行分组时,如果想使用函数,仅能使用分组函数,不能使用别的函数
- 由于执行的顺序是 where -> group by -> having -> select,因此分组函数不能出现在 where 之后(此时都没有分组完,怎么用分组函数?)
分组函数的执行原则:如果有group by 语句,先按照分组条件进行分组,然后对每一组数据执行分组函数;如果没有分组语句group by的话,整张表的数据自成一组。
分组函数包括五个:
- max:最大值
- min:最小值
- avg:平均值
- sum:求和
- count:计数,