SQL学习记录

SQL学习

在这里插入图片描述

第一章:简单查询

1.1 语法:

select col_name1, col_name2…
from tb_name;
语法解释:从数据源tb_name中找到col_name1,col_name2、…这几列数据
子句:某个关键词及其紧跟的内容
例如:select ename
select 子句:可跟 数据源的具体字段、函数、常量、, 子句中跟随的内容决定了查询结果的内容、列数、顺序、但是不影响行数,其中表示数据源中所有列
常量:一个保持不变的值,例:‘员工姓名’

例题:
–1.查看员工信息表EMP中员工的所有信息
select * from emp;
select EMPNO, ENAME, JOB, MGR, HIREDATE, SAL, COMM, DEPTNO from emp;
–2.查看员工信息表EMP中员工的部分信息,例如姓名、岗位和薪资,或员工编号、姓名和部门编号
select ename, job, sal from emp;
select empno, ename, deptno from emp;
–3.查看员工信息表EMP中员工的姓名、部门编号、岗位和薪资
select ename, deptno, job, sal from emp;
–4.查看员工信息表EMP中员工的姓名,并在姓名列前加一列常量,内容是:“员工姓名”这几个字
select ‘员工名字’,ename from emp;
1.2 别名
列别名:给列取别名,用来在查询结果中以代替本名显示
select col_name as col_akias … from tb_anme;
(as 可以省略)
表别名:给表取别名,原来代替原本的表名
select tb_name.col_name … from tb_name tb_alias;
注意:
1)表别名和列别名都仅仅在此SQL语句范围内有效,不会改变本名
2)别名不建议出现除_以外的特殊字符,如果非要加入,要在别名的两侧用双引号(" ")引起
3)别名不建议出现中文
例题:
–5.用“员工姓名”代替ENAME,用“工作岗位”代替JOB
select ename 员工姓名, job 工作岗位 from emp;
–6.用T代替EMP表,查看EMP表中的ENAME和JOB字段
select ename, job from emp T;
–7.同时使用列别名与表别名
select ename 姓名,sal from emp T;
思考:同样是员工姓名,何时要用单引号引起,什么时候不用单引号引起?
–那个不在正常运行?
select ‘员工姓名’ “员工姓名” from emp;
select ‘员工姓名’ 员工姓名 from emp;
select ‘员工姓名’ as ‘员工姓名’,ename from emp;
select ‘员工姓名’ , ‘员工姓名’,ename from emp;

答案:select ‘员工姓名’ as ‘员工姓名’,ename from emp; 不能正常运行,
作为数据两侧要用单引号
作为列名两侧用双引号
例题:
–8.对常量’员工姓名’命列别名“员工姓名”
select ‘员工姓名’ 员工姓名,ename from emp;
1.3 连接符:||
将两个字段链接在一起和成一个字段
–9.将ENAME和JOB字段合并在一起
select ename||job from emp;
–10.将常量与表字段合并在一起
select ‘员工姓名是:’||ename from emp;
1.4 其他补充
 distinct 是去重关键字,用于去除查询结果的重复数据,
例子:
–去除重复的部门编号
select distinct deptno from emp;
 where 用于限制返回结果的行数。
例子:
–工资大于1500的员工信息
select * from emp where > 1500;

思考:
select col_name1, col_name2…
from tb_name;
这些地方为什么这样写?
答案:

第二章:条件查询

2.1 语法

select col_name1,col_name2 from tb_name where condintion;
语法解释:
在tb_name中按照条件condition进行筛选,从条件成立的数据中进行查找col_name1,col_name2,…列的数据。
补充:dual表:仅含有一行一列的表,一般用于查询常量

2.2 模糊查询

语法:
–符合目标格式
select col_list from tb_name where col_name like ‘目标格式’,
–不符合目标格式
select col_list from tb_name where col_name not like ‘目标格式’,
通配符:
:有且只有一个字符
%:有零个或者一个或者多个字符
例题:
–1.查找姓名前边是SMIT、最后一位不确定的员工信息
select * from emp where ename like 'SMIT
’;
–2.查找姓名前边是SM、后边是TH、中间有一位不确定的员工信息
select * from emp where ename like ‘SM_TH’;
–3.查找姓名总共有五位的员工信息
select * from emp where ename like ‘_____’;
–4.查找姓名前边是S、后边是H、中间有三位不确定的员工信息
select * from emp where ename like ‘S___H’;
–5.查找姓名以S开头的员工信息
select * from emp where ename like ‘S%’;
–6-9
–6.查找姓名不以S开头的员工信息
select * from emp where ename not like ‘S%’;
–7.查找名字中带有A字母的员工信息
select * from emp where ename like ‘%A%’;
–8.查找姓名总共有5位且首字母是A的员工信息
select * from emp where ename like ‘A____’;
–9.查找姓名是以A开头且倒数第二位是M的员工信息
select * from emp where ename like ‘A%M_’;
拓展:
1、模糊查询中的转译设置:escape’转移字符’
例子:
–查询姓名当中含有% 的员工的信息
select * from emp where ename like ‘%%%’ escape '’;
–注意:
–1、只有_和%需要转移
–2、每一个需要转义的字符前面都需要加转义符
–3、转义符的范围仅限于紧跟其后的员工字符
2、两个英文单引号表达一个英文单引号的含义
–下面哪一个可以正确运行呢?
select * from emp where ename like ‘%’%’ escape ‘’;
select * from emp where ename like ‘%’’%’ escape '
’;

2.3逻辑运算符的用法

语法:
select col_list from tb_name where col_name1 = value|col_name2|expr
逻辑表达运算符:= < > <= >= <> !=

补充:
–相关条件 where 后面数据属于表格内容
–非相关条件 where 后面的数据不属于表格内容
select * from emp where 1=1;–恒成立
select * from emp where 1=0; --恒不成立
全盘扫描:挨个判断表格中数据是否满足条件
索引扫描:先对表格数据进行排序,在定位到满足条件附近进行判断
例题:
–1.查询10号部门的员工信息
select * from emp where deptno = 10;
–2.薪资超过2500的员工信息
select * from emp where sal > 2500;
–3.查询薪资小于1000的员工
select * from emp where sal < 1000;
–4.查询10号部门之外的员工信息
select * from emp where deptno != 10;
注意点:
1)空值不能参与运算
比较【薪资超过1000与不超过1000的员工总计】和【奖金超过1000与不超过1000的员工总计】
select count() from emp where sal > 1000;–薪资大于1000
select count(
) from emp where sal <= 1000; --薪资小于1000

select ‘大小’ from dual
where (select count(*) from emp where sal > 1000)

(select count(*) from emp where sal <= 1000);

select count() from emp where comm > 1000;–奖金大于1000
select count(
) from emp where comm <= 1000; --奖金小于1000

–下面计算出来的总人数不等于表中的总人数,结论:空值不参与计算
select ‘大小’ from emp
where (select count(*) from emp where comm > 1000)

(select count(*) from emp where comm <= 1000);

–查询有奖金的员工信息
select * from emp where comm > 0;
–查询无奖金的员工信息
select * from emp where comm = 0;

select * from emp where nvl(comm,0) = 0;
–nvl(value1, value2)value1是空值返回value2,value1 非空,返回value1
2)区分数据类型:数值型、字符型、日期型
数值型:纯数字内容,正常的数值判断
字符型:包括字母、汉字、符号、数字,转换为ASCII码进行比较
日期型:存放时间、根据日期早晚进行比较判断

数值型局右
字符型居左
日期型居左,右边有员工按钮(可以打开一个日历)
–字符型比较,ASCII码进行比较,这里有一个小问题,使用> 符号,查询结果带有B的
select * from emp where ename > ‘B’;

select ascii(‘B’) from dual;
select ascii(‘甲’) from dual;–48343
select ascii(‘古’) from dual;–47557
select ascii(‘文’) from dual;–52932

select chr(48343)||chr(47557)||chr(52932) from dual;

–字符型:差一个字母差一个符号都不行–数据严格区分大小写,代码不区分
–1.查询姓名是SMITH的员工信息
select * from emp where ename = ‘SMITH’;
–2.查询姓名是SMiTH的员工信息
select * from emp where ename = ‘SMiTH’;–不存在、严格区分大小写
–3.查询姓名是smith的员工信息
select * from emp where ename = ‘smith’;
–4.查询姓名是SMIT的员工信息
select * from emp where ename = ‘SMIT’;
–5.查询岗位是SALESMAN的员工信息
select * from emp where job = ‘SALESMAN’;
–6.查询岗位是SALESMaN的员工信息
select * from emp where job = ‘SALESMAN’;
–7.查询岗位是SALESMAN的员工信息(不区分大小写)
select * from emp where job = ‘SALESMAN’;

–补充 手动修改数据的方式:for update的知识点

–函数拓展:
–大小写转换函数:UPPER()和 LOWER()
select * from emp where ename = upper(‘smith’); --可以查询
select * from emp where ename = lower(‘SMITH’);
–ASCII码与字符转换:ASCII()和 CHR()

–日期型:时间对不对得上
–查询入职日期为1980年12月17号的员工信息
–日期要和日期格式进行比较,字符型转换为日期,使用to_date()函数, 前后都需要加单引号
select * from emp where hiredate = to_date(‘1980/12/17’,‘YYYY/MM/DD’);
–HIREDATE = 1980/12/17 ? HIREDATE = '1980/12/17’ ?

–to_char() 可以提取自己需要的字符型数据
select to_char(hiredate,‘YYYY’) from emp;
select to_char(hiredate,‘MM’) from emp;
select to_char(hiredate,‘DD’) from emp;
–to_date() 前后数据的格式应该保持一致!!!
select to_char(hiredate,‘YYYY/MM/DD’) from emp;

–一般情况下无法直接写出一串日期型数据,而是通过转换函数,将字符型数据转换为日期函数
–函数拓展:
–字符串转日期:TO_DATE(‘字符串’,‘与字符串对应的日期格式’)
–日期转字符串:TO_CHAR(‘日期’,‘日期转成字符串的目标格式’)
–将日期转换为字符类型,也可以进行比较
–既然是比较日期,还是转换为日期比较严谨?
select * from emp where to_char(hiredate,‘YYYY/MM/DD’) = ‘1980/12/17’;

–查询1981年劳动节以前入职的员工信息
–字符转换为日期,前后都要加单引号
select * from emp where hiredate < to_date(‘1981/05/01’,‘YYYY/MM/DD’);
select * from emp where to_char(hiredate,‘YYYY/MM/DD’) < ‘1981/05/01’;
select * from emp where to_char(hiredate,‘YYYYMMDD’) < ‘19810501’;
select ename, hiredate from emp;

2.4 包含查询

语法:
select col_list from tb_name where col_name in (集合)
–只要在该集合中条件成立
select col_list from tb_name where col_name not in (集合)
–只要不在该集合中条件成立

集合:一组有相同属性(相同数据类型)的数据

例题:

–1.查询部门编号是10号或20号的员工信息
select * from emp where deptno = 20 or deptno = 10;
select * from emp where deptno in (20,10);
–2.查询薪资是3000或5000的员工信息
select * from emp where sal = 3000 or sal = 5000;
select * from emp where sal in (3000,5000);
–3.查询岗位是SALESMAN或者MANAGER的员工信息
select * from emp where job = ‘SALESMAN’ or job = ‘MANAGER’;
select * from emp where job in (‘SALESMAN’, ‘MANAGER’);

–4.查询岗位既不是SALESMAN也不是MANAGER的员工信息
select * from emp where job not in (‘SALESMAN’,‘MANAGER’);

–5.查询入职时间是1980年12月17号或者1981年2月20号的员工信息

–将hiredate转换为字符类型,再和需要查询的日期进行比较
select to_char(hiredate,‘YYYYMMDD’) from emp;
select * from emp where to_char(hiredate,‘YYYYMMDD’) in (‘19801217’,‘19810220’);

–将日期转换为字符类型
select to_char(hiredate,‘YYYY/MM/DD’) from emp;
select * from emp
where to_char(hiredate,‘YYYY/MM/DD’) in (‘1980/12/17’, ‘1981/02/20’);
select ‘1980/12/17’ from dual;

–将需要查询的日期先改写为日期类型,再和hiredate进行比较
select to_date(‘19801217’,‘YYYY/MM/DD’),to_date(‘19810220’,‘YYYY/MM/DD’) from dual;
select * from emp where hiredate
in (to_date(‘19801217’,‘YYYY/MM/DD’),to_date(‘19810220’,‘YYYY/MM/DD’));
注意:
1)集合与比较的字段也是要有相同的数据属性,即相同的数据类型
2)集合中的数据类型也要保持一致

2.5范围查询

语法:
select col_list from tb_name where col_ name between num1 and num2;
注意点:
1)num1 <= num2
2) 包含边界值
例题:
–1.查询薪资在1000以上的员工
select * from emp where sal > 1000;
–2.查询薪资在3000以下的员工
select * from emp where sal < 3000;
–3.查询薪资在1000到3000之间的员工
select * from emp where sal between 1000 and 300;

–4.查询1981年入职的员工
–19810102
–19811231
select * from emp where to_char(hiredate,‘YYYYMMDD’) between ‘19810101’ and ‘19811231’;
–将两个数据转换为日期型数据,再与hiredate 进行比较
select to_date(‘19810102’,‘YYYYMMDD’) from dual;
select to_date(‘19811231’,‘YYYYMMDD’) from dual
select * from emp
where hiredate between to_date(‘19810102’,‘YYYYMMDD’)
and to_date(‘19811231’,‘YYYYMMDD’);

–首先将hiredatede 年份信息提取出来 再与1981进行比较
select to_char(hiredate,‘YYYY’) from emp;
select * from emp where to_char(hiredate,‘YYYY’) = ‘1981’;

2.6 null值判断

语法:
select col_list from tb_name where col_name is null;
–是空值
select col_list from tb_name where col_name is not null;
–非空值
–空值不参与计算
例题:
select * from emp;
–空值不参与运算
select * from emp where comm < 1000;–3
select * from emp where comm >=1000;–1
select * from emp for update;

select * from emp where ename like ‘A%’;–2
select * from emp where ename not like ‘A%’;–12
select * from emp where ename in (‘ALLEN’,‘JAMES’);–2
select * from emp where ename not in (‘ALLEN’,‘JAMES’);–12

–1.查找有奖金的员工信息
select * from emp where comm > 0;–3
select * from emp where nvl(comm,0) > 0;–3
–2.查找无奖金的员工信息
select * from emp where comm = 0;–1
select * from emp where nvl(comm,0) = 0;–11

–3.查找公司的大领导信息
select * from emp where job = ‘PRESIDENT’;
select * from emp where mgr is null;
补充:字符中的空格和数值中的0不算在空值之内

2.7 any 和 all

any : 任意一个
all : 所有全部
=any(集合)

any(集合) :大于最小值
<any(集合):小于最大值

=all(集合)

all(集合):大于最大值
<all(集合):小于最小值
例题:
– = ANY(集合)
select * from emp where sal in (1100,3000,5000);–4
select * from emp where sal = any (1100,3000,5000);–4
– > ANY(集合)
select * from emp where sal > any (1100,3000,5000);–11,大于集合中最小值
–< ANY(集合)
select * from emp where sal < any (1100,3000,5000);–13,小于集合中最大值
– = ALL(集合)
select * from emp where sal = all (1100,3000,5000);–0,
– > ALL(集合)
select * from emp where sal > all (1100,3000,5000); --0,大于集合中最大值
– < ALL(集合)
select * from emp where sal < all (1100,3000,5000);–2,小于集合中最小值

2.8 布尔连接

语法:
select col_name from tb_name where condition1 and condition2
select col_name from tb_name where condition1 or condition2
条件链接关键词:and 和(且) or 或

注意:
1)布尔连接连接的两个字段类型可以相同 也可以不同
2)and 和 or 一起使用时 and 的优先级 高于or
3)小括号内部内容的优先级最高
例题:
–1.查询薪资超过1000并且小于3000的员工信息
select * from emp where sal > 1000 and sal <3000;
–2.查询部门编号是10号或20号的员工信息
select * from emp where deptno = 20 or deptno = 10;
–3.查询岗位是销售SALESMAN,并且奖金超过400的员工信息
select * from emp where job = ‘SALESMAN’ and nvl(comm,0) > 400;
–4.查询20号部门的经理
select * from emp where job = ‘MANAGER’ and deptno = 20;
–5.查询所有20号部门的员工或岗位是MANAGER的员工信息
select * from emp where deptno = 20 or job = ‘MANAGER’;
–6.查询10号部门的部门经理或20号部门的分析师ANALYST
select *
from emp
where (deptno = 10 and job = ‘MANAGER’) or (deptno = 20 and job = ‘ANALYST’);
作业:
–作业
–1.查询(20号部门的)员工姓名、岗位、薪资
select ename, job, sal from emp where deptno = 20;
–2.查询工资超过3000的员工的姓名、薪资
select ename, sal from emp where sal > 3000;
–3.查询非10号部门的员工的所有信息
select * from emp where deptno != 10;
–4.查询员工姓名为SMITH的员工的所有信息
select * from emp where ename = ‘SMITH’;
–5.查询1981年2月20号入职的员工的姓名和薪资
select ename, sal from emp where hiredate = to_date(‘19810220’,‘YYYYMMDD’);
select ename, sal from emp where to_char(hiredate,‘YYYYMMDD’) = ‘19810220’;
–6.查询入职日期早于1982年1月1日的所有员工的姓名、入职日期
select ename, hiredate from emp where hiredate < to_date(‘19820101’,‘YYYYMMDD’);
select ename, hiredate from emp where to_char(hiredate,‘YYYYMMDD’) < ‘19820101’;
–7.找出奖金(COMM字段)大于0的员工信息
select * from emp where nvl(comm,0) > 0;

–8.查询姓名中首位是S的员工的姓名、岗位
select ename, job from emp where ename like ‘S%’;
–9.查询姓名中包含S的员工的姓名、岗位
select ename, job from emp where ename like ‘%S%’;
select * from emp;
–10.查询员工姓名以S开头,且姓名总长度为5位的员工的所有信息
select * from emp where ename like ‘S____’;
–11.查询员工姓名前两位是SM,后两位是TH,中间一位不清楚具体字母的员工的所有信息
select * from emp where ename like ‘SM_TH’;
–12.查询员工姓名至少有四位,且倒数第三位是I的员工的所有信息
select * from emp where ename like ‘%I_’;
select * from emp where ename like ‘_%I__’;
–13.查询员工姓名中包含IT的员工的所有信息
select * from emp where ename like ‘%I%T%’ or ename like ‘%T%I%’ ;

–14.查询岗位是MANAGER或SALESMAN的员工信息
select * from emp where job = ‘MANAGER’ or job = ‘SALESMAN’;
select * from emp where job in(‘MANAGER’ ,‘SALESMAN’);
–15.查询SMITH和SCOTT的详细信息
select * from emp where ename = ‘SMITH’ or ename = ‘SCOTT’;
–16.查询10号或20号部门的员工信息
select * from emp where deptno = 10 or deptno = 20;
select * from emp where deptno in(10,20);
–17.查找工资在1000-3000之间的员工姓名、工作、工资(包含1000和3000)
select ename, job, sal from emp where sal between 1000 and 3000;
select ename, job, sal from emp where sal<=3000 and sal >=1000;
–18.查询入职时间在1980年或1981年的员工信息
select * from emp where to_char(hiredate,‘YYYY’) between ‘1980’ and ‘1981’;
select * from emp where to_char(hiredate,‘YYYY’) in(‘1980’,‘1981’);
– (查询入职时间在1980年1月1日到1981年12月31日之间的员工信息)
select * from emp where to_char(hiredate,‘YYYYMMDD’) between ‘19800101’ and ‘19811231’;
select * from emp where hiredate between to_date(‘19800101’,‘YYYYMMDD’) and to_date(‘19811231’,‘YYYYMMDD’);
–19.查询没有部门归属的员工姓名和编号
select ename, empno,deptno from emp where deptno = 0 or deptno is null;
select ename,empno from emp where deptno not in(10,20,30,40);
–20.查询公司大BOSS的详细信息
select * from emp where job = ‘PRESIDENT’;
select * from emp where mgr is null;

–21.查找姓名总共有5位、且不是以A开头的员工信息
select * from emp where ename not like ‘A____’ and ename like ‘_____’;
–22.查出10号部门的办事员和30号部门的经理
select * from emp where deptno = 10 and job = ‘CLERK’ or deptno = 30 and job = ‘MANAGER’;
–23.查出10号部门的所有人、30号部门的部门经理以及所有岗位是分析师的员工
select * from emp where deptno = 10 or (deptno = 30 and job = ‘MANAGER’) or job = ‘ANALYST’;
–24.查出10号及30号部门的办事员CLERK及经理MANAGER
select * from emp where (deptno=10 or deptno=30) and (job = ‘CLERK’ or job = ‘MANAGER’);
select * from emp where deptno in(10,30) and job in(‘CLERK’,‘MANAGER’);
select * from emp where (deptno=10 and job = ‘CLERK’ ) or (deptno=30 and job = ‘CLERK’ ) or (deptno=10 and job = ‘MANAGER’) or (deptno=30 and job = ‘MANAGER’);
–25.找出奖金(COMM)高于工资的员工
select * from emp where nvl(comm,0) > sal;
–26.找出工资高于奖金3倍的员工
select * from emp where sal > (nvl(comm,0)*3);
–27.找出不收取奖金或收取的奖金低于1000的雇员
select * from emp where (nvl(comm,0)=0 or nvl(comm,0)<1000);
–28.显示所有雇员的姓名和日工资(一个月假设为30天)
select ename, sal/30 from emp ;
–29.查找工资在1000-3000之间的员工姓名、工作、工资(不含1000和3000)
select ename, job, sal from emp where sal < 3000 and sal > 1000;
–30.查询姓名中只有一个A字母的员工
select * from emp where ename like ‘%A%’ and ename not like ‘%A%A%’;

第三章:分组排序

3.1 order by

语法:
select col_list from tb_name order by odr_condition [asc|desc];
语法解释:对于tb_name中查询到的col_list数据按照odr_condition 进行排序
asc 为升序,desc 为降序

补充:
1)order by 后可以跟列名,别名,位次
2)空值不参与运算而且视为正无穷
例子:
select empno,ename,job,sal from emp order by sal;–列名
select empno,ename,sal 薪资 from emp order by sal;–别名
select empno,ename,sal job from emp order by 3;–位次

–1.查询员工姓名、岗位及薪资,并将查询结果按薪资升序排列
select ename,job,sal from emp order by sal ;
–.查询员工姓名、岗位及部门编号,并将查询结果按部门编号降序排列
select ename,job,deptno from emp order by deptno desc;
–3.查询所有员工信息,并按工资由高到低排序,如果工资相同按部门编号由高到低排序
select * from emp order by sal,deptno desc;

3.2 group by

分组查询
语法:select col_name ,聚合函数,常量 from tb_name group by col_list;
语法解释:
对于数据源tb_name 按照col_list 进行分组 ,统计各组的情况

1、group by 可对查询结果根据指定列进行分组
例如:
–按照部门编号进行分组查询,行数减少
select deptno from emp group by deptno;
2、思考为什么不能采取select * 的方式进行分组?
思考:group by 使用后 select 后面只能出现group by 后出现过的列

聚合函数:
概念:把分散的数据按照某种规则分成不同的组、或所有数据整体作为一个组,对组级别的数据进行分析,每组得到一个返回值。
五个聚合数据:
sum ():求和
max():求最大值
min():求最小值
avg():求平均数
count():计数
var_pop(value) 方差
select avg(sal),var_pop(sal) from emp;
例子:
–1.查询整个公司的薪资合计
select sum(sal) from emp;
–2.查询整个公司的平均薪资
select avg(sal) from emp;
select max(sal) from emp;–工资最大值
select min(sal) from emp;–工资最小值
select avg(sal) from emp;–工资平均值

select count(empno) from emp;–15
select count(1) from emp;–15
select count(*) from emp;–15
select count(comm) from emp;–5
–空值不参与运算
注意:
1、只有出现在group by之后的结果列,才可以出现在select 之后,因为group by 之后行数会减少
2、对于含有group by 子句的SQL语句,select 之后值允许出现:
1)group by 中出现的字段
2) 聚合函数
3)常量

3.3 having

分组过滤
语法:
select col_list ,聚合函数,常量
from tb_name
group by col_list
having 以聚合函数为基础的条件判断

语法解释:
对于数据源tb_name按照col_list 分组,统计各组的分析情况,并对分析结果进行筛选
例子:
–查询个部门最高工资
select max(sal), deptno from emp group by deptno;

–1、查询部门最低薪资大于1000的部门号
select deptno from emp group by deptno having min(sal) > 1000;
–2、统计各部门中,最高薪资低于5000的部门有哪些
select deptno from emp group by deptno having max(sal) < 5000;
–3、统计除10号部门的其他部门中,哪些部门的最高薪资达到三千
select deptno from emp
where deptno != 10 group by deptno having max(sal) > 3000;

书写顺序
select
from
where
group by
having
order by

读取顺序
from
where
group by
having
order by

第四章:函数

已经封装好,了解会用就好

一、转换函数

作用范围:
针对不同的数据类型相互转化使用,转化是可以同时指定目标类型与格式
分类:
按专函的形式:
显性转换:用户主动执行的转换函数而实现的
隐形转换:系统自动执行转换函数而实现的
按转换的目标格式:
转字符:to_char
转数值:to_number
转日期:to_date

1.1 转换函数:to_char
1.1.1数字转字符

无指定格式:单纯的由数值转换为字符
有指定格式:将数值转换为字符时,指定格式
指定格式包括指定精度与指定货币
指定精度:
数值转字符的通配符:通过0或9来代指该为内容
9:指任意数字,若整数位,该位置无数字,则合适不生效,小数位该位无数字以0 补全
0:指任意数字,若整数为该位无数字,则强制显示0,小数为则一般不用0 指代

注意:
1)若指定格式,转换过程中易出现空格,所有常常会搭配去空格函数使用
2)转换过当中遇到小数点精度过低的过程,则会遵循四舍五入,整数位精度过低的情况,则会显示为#
3)可添加千分符
举例:
select to_char(123.45,‘999.99’) from dual;–将数值型数据转换为字符型数据
select to_char(123.45,‘099.99’) from dual;–0在整数位指代数字
select to_char(123.45,‘0099.99’) from dual;–0 指定格式时,整数位没有是数字,用0补全
select to_char(123.45,‘99099.99’) from dual;–9 指定格式时 整数位没有数字 不需要补全
select to_char(123.45,‘9900099.00’) from dual;–0指定格式时需要补全
select to_char(12345.67,‘999,999.999’) from dual;–9 指定格式时 小数位需要用0补全
select to_char(123456789.987,‘999,999,999.999’) from dual;
select to_char(123456789.987,‘99999,9999.999’) from dual;–将前面的数值型数据转换位指定的字符类型
select to_char(999.99,‘999.99’) from dual;–将数值型数据转换位字符型数据
select to_char(999.99,‘999.9’) from dual;–小数位精度不够四舍五入 导致整数位精度不够? 出现###

指定货币
$:美元符号
L:当地货币
举例:

select to_char(123.45,’$999.99’) from dual;–将数值型数据转换位美元
select to_char(123.45,‘999.9$9’) from dual;–转换成功!
select to_char(123.45,‘99$9.99’) from dual; --转换成功
select to_char(123.45,‘L999.99’) from dual;–将数值型数据转换位当地货币符号
select to_char(123.45,‘99L9.99’) from dual;–报错

1.1.2日期转字符

拓展:获取当前相同日期的方法
select sysdate,systimestamp from dual;–获取当前日期
日期格式的设置:
通过一些固定字母或关键词来指代日期中的某一项内容,其中可以穿插一些分隔符,且这些关键词可以随意搭配以及更改顺序
1)年份
YYYY:四位的年份
YYY,YY,Y:分别表示后三位、、两位、以及以为的年份
–年
select to_char(sysdate,‘YYYY/MM/DD’) from dual;
select to_char(sysdate,‘YYY’)from dual;
2)季度
Q:一年中地几个季度(一位)
–季度
select to_date(‘20220908’,‘YYYYMMDD’),
to_char(to_date(‘20220908’,‘YYYYMMDD’),‘Q’) from dual;–3
3)月份
MONTH:月的全称(右侧空格补全九位)–英文:nls_date_language = american
MON:三位字符夫人月份缩写 --英文:nls_date_language = american
MM:一年中的第几个月(两位)
–月
–MONTH 全称
select sysdate,to_char(sysdate,‘MONTH’)from dual;–1月
select sysdate,to_char(sysdate,‘MONTH’,‘nls_date_language=american’)from dual;–JANUARY
select to_date(‘20220910’,‘YYYYMMDD’),
–MON 缩写
to_char(to_date(‘20220910’,‘YYYYMMDD’),‘MON’) from dual;–9月
select to_date(‘20220910’,‘YYYYMMDD’),
to_char(to_date(‘20220910’,‘YYYYMMDD’),‘MON’,‘nls_date_language=american’) from dual;–SEP
– MM 一年中 第几个月
select to_date(‘20220910’,‘YYYYMMDD’),
to_char(to_date(‘20220910’,‘YYYYMMDD’),‘MM’) from dual;–09
4)星期
WW:一年中的第几个星期,从第一天开始算起,七天算一周,与星期几无关
IW:一年中的第几个星期,星期一位本周第一天,每年莫最后员工周不足四天算至下一年第一周,足四天将下年本周的剩余时间一同算作本年最后一周
w:一月中的第几个星期,从第一天开始算起,一个七天算作一周,和星期几无关
DAY:星期几全称(右侧空格补足九位)–英文;nls_date_language = american
DY : 星期几缩写 --英文:nls_date_amerdican
–星期
–WW 一年中的第几个星期,从第一天开始算,和星期无关
select to_date(‘20220107’,‘YYYYMMDD’),
to_char(to_date(‘20220107’,‘YYYYMMDD’),‘WW’) from dual;–01
select to_date(‘20220109’,‘YYYYMMDD’),
to_char(to_date(‘20220109’,‘YYYYMMDD’),‘WW’) from dual;–02
–IW 一年中的而第几个星期,和星期几有关 最后一个星期不足四天,归下一年第一个星期,足四天位今年最后一周
select to_date(‘20220109’,‘YYYYMMDD’),
to_char(to_date(‘20220109’,‘YYYYMMDD’),‘IW’) from dual;–01,
select to_date(‘20211231’,‘YYYYMMDD’),
to_char(to_date(‘20211231’,‘YYYYMMDD’),‘IW’) from dual;–52
select to_date(‘20220101’,‘YYYYMMDD’),
to_char(to_date(‘20220101’,‘YYYYMMDD’),‘IW’) from dual;–52,算2021最后一周
select to_date(‘20191231’,‘YYYYMMDD’),
to_char(to_date(‘20191231’,‘YYYYMMDD’),‘IW’) from dual;–01 ,算2020第一周
–W 一月中的第几个星期,每月第一天开始算第一周第一天,和星期几无关
select to_date(‘20220101’,‘YYYYMMDD’),
to_char(to_date(‘20220101’,‘YYYYMMDD’),‘W’) from dual;–1
select to_date(‘20220131’,‘YYYYMMDD’),
to_char(to_date(‘20220131’,‘YYYYMMDD’),‘W’) from dual;–5
select to_date(‘20220201’,‘YYYYMMDD’),
to_char(to_date(‘20220201’,‘YYYYMMDD’),‘W’) from dual;–1
–星期几
–DAY 全称
select to_char(to_date(‘20220101’,‘YYYYMMDD’),‘DAY’) from dual;–星期六
select to_char(to_date(‘20220101’,‘YYYYMMDD’),‘DAY’,‘nls_date_language=american’) from dual;–SATUDAY
–DY 缩写
select to_char(to_date(‘20220101’,‘YYYYMMDD’),‘DY’) from dual;–星期六
select to_char(to_date(‘20220101’,‘YYYYMMDD’),‘DY’,‘nls_date_language=american’) from dual;–SAT

5)天
D:星期中的第几天 --从星期日开始算第一天
DD:月份中的第几天
DDD:年份中的第几天
–天
–20221231 星期五
–D 星期中的第几天–星期日算第一天
select to_char(to_date(‘20211231’,‘YYYYMMDD’),‘D’) from dual;–6
–DD 月份当中第几天
select to_char(to_date(‘20221231’,‘YYYYMMDD’),‘DD’) from dual;–31
–DDD 一年当中第几天
select to_char(to_date(‘20221231’,‘YYYYMMDD’),‘DDD’) from dual;–365

6)小时
HH12:一天中的第几个小时(12小时制)
HH24:一天中的第几个小时(24小时制)
select sysdate,to_char(sysdate,‘HH12 PM’),to_char(sysdate,‘HH12 AM’) from dual;

7)分钟
MI:一小时中第几分钟
8)秒
SS:一分钟中的第几秒
9)毫秒
FF: 毫秒(默认6位)
FF3,FF6: FF 后跟数字表示毫秒的显示位数

– 小时
–HH 24
select to_date(‘20221231193030’,‘YYYYMMDD HH24:MI:SS’) from dual;–2022/12/31 19:30:30
select to_char(to_date(‘20221231193030’,‘YYYYMMDD HH24:MI:SS’),‘HH24’) from dual;–19
–MI 分钟
select to_char(to_date(‘20221231193030’,‘YYYYMMDD HH24:MI:SS’),‘MI’) from dual;–30
–SS 秒
select to_char(to_date(‘20221231193030’,‘YYYYMMDD HH24:MI:SS’),‘SS’) from dual;–30

select systimestamp,to_char(systimestamp,‘FF’) from dual;

公认的、比较标准的写法
select sysdate,
to_char(sysdate,‘YYYY-MM-DD HH24:MI:SS’),
to_char(sysdate,‘YYYY/MM/DD HH24:MI:SS’),
to_char(sysdate,‘YYYYMMDD HH24:MI:SS’),
to_char(sysdate,‘YYYY-MM-DD’),
to_char(sysdate,‘YYYY/MM/DD’),
to_char(sysdate,‘YYYYMMDD’),
systimestamp,
to_char(systimestamp,‘YYYY-MM-DD HH24:MI:SS.FF’)
from dual;
1.2 转换字符 to_number
1.2.1将只含有数字的字符转化位数值
1.2 2去掉字符串中的特定符号 并将剩下的数字转换位数值
认定符号包括:千分符和货币符号
select to_number(‘123’) from dual;
select to_number(‘000123’) from dual;
select to_char(0123)from dual;

–去掉千位符
select to_number(‘1,111.1’,‘9999.99’) from dual;
–去掉货币单位
select to_number(’$99.99’,’$999.99’) from dual;
select to_number(‘¥123.45’,‘L999.99’) from dual;
1.3 转换字符 to_date
1.31 to_date(字符串表示的日期,‘与前者对应的日期格式’)

注意:
1)日期数据不同于字符和数值,日期数据存放的时有关该日期的所有书局,通过to_char指定不同的目标格式,可以转出不同的内容
select to_date(‘20210624’,‘yyyymmdd’) from dual;
sselct to_char(to_date(‘20210624’,‘yyyymmdd’),‘hh24:mi:ss’) from dual;
2)出于不同工具日期格式不同的原因,很多项目以字符格式存储日期

二、字符型函数

 针对字符、且返回值仍是字符的函数

1. 连接

–连接
–concat(str1,str2) 为什么要用concat()?-- 不是所有数据库都有||
select concat(ename,sal) from emp;
select concat(concat(ename,sal),job) from emp;–反复嵌套使用
select ename||sal||job from emp;

2. 大小写转换

–大小写函数
–upper(str) 改为大写
–lower(str) 改为小写
select ‘ABC’,lower(‘ABC’) from dual;
select upper(ename),lower(upper(ename)) from emp;
–initcap 首字母大写 后面的小写
select initcap(ename) from emp;
select ‘AMITH ALLEN’,initcap(‘AMITH ALLEN’) from dual;–Amith Allen
select ‘AMITHALLEN’,initcap(‘AMITHALLEN’) from dual;–Amithallen
select ‘AMITH’‘ALLEN’,initcap(‘AMITH’‘ALLEN’) from dual;–Amith’Allen
select ‘AMITH2ALLEN’,initcap(‘AMITH2ALLEN’) from dual;–Amith2allen
select ‘AMITH ALLEN WADRD’,initcap(‘AMITH ALLEN WADRD’) from dual;–Amith Allen Wadrd

3. 替换

–替换
–replace(str,s1,s2) 将str中的s1 用s2 替换, 其中s1、s2都是看作一个整体
select replace(‘ABCDE’,‘B’,‘b’) from dual;–AbCDE
select replace(‘ABCDE’,‘BC’,‘MN’) from dual;—AMNDE
select replace(‘ABCDE’,‘ABCDE’,‘W’) from dual;–W
select replace(‘ABCDEABCDE’,‘BC’,‘MN’) from dual;–AMNDEAMNDE 全部替换
select replace(‘ABCDEF’,‘CD’,‘搞笑’) from dual;–AB搞笑EF
select replace(‘HE hate YOU’,‘HE’,‘I’) from dual;–I hate YOU
select replace(‘ABCD EF’,‘D E’,‘WW’) from dual;–ABCWWF
select replace(‘ABCDEF’,‘A’,‘a’),replace(replace(‘ABCDEF’,‘A’,‘a’),‘B’,‘b’) from dual;–aBCDEF–abCDEF
select replace(‘2022/05/20’,’/’,’-’) from dual;–2022-05-20
select ename,replace(ename,‘A’,‘a’) from emp;

4. 去除

–去除函数
–trim():去除指定字符串或者字段两侧的空格
–ltrim():去除指定字符串或者字段左侧空格
–rtrim():去除指定字符串这字段右侧空格

select trim(’ AAA ‘) from dual;–去除两侧空格
select trim(’ AAA BBB ‘) from dual;–去除两侧空格
select trim(’@ AAA BBB @’) from dual;–@ AAA BBB @ --虽然两侧有空格但不是在最边上

select ltrim(’ AAA ‘) from dual;–去除左侧空格
select ltrim(’ AAA BBB ‘) from dual;–去除左侧空格
select ltrim(’@ AAA BBB @’) from dual;–@ AAA BBB @ --虽然两侧有空格但不是在最边上

select rtrim(’ AAA ‘) from dual;–去除右侧空格
select rtrim(’ AAA BBB ‘) from dual;–去除右侧空格
select rtrim(’@ AAA BBB @’) from dual;–@ AAA BBB @ --虽然两侧有空格但不是在最边上
事实上,去除函数去除空格仅仅是默认用法,去除函数可以用来去除字符串或者字段当中的指定部分

完整用法:
ltrim(str[,s]) :去除str左侧的s ,如果s 省略则去除空格
rtrim(str[,s]) :去除str右侧的s ,如果s 省略则去除空格
trim([leading/trailing/both] [s from] str):去除字符串s,具体去除左侧/右侧/两侧 根据[leading/trailing/both]决定,若省略该参数,则默认去除两侧,参数 [s from] 决定被去除内容,若省略则默认去除空格
–举例:
–1.去除姓名左侧的S
select ltrim(ename,‘S’) from emp;
select trim(leading ‘S’ from ename) from emp;
–2.去除姓名右侧的S
select rtrim(ename,‘S’) from emp;
select trim(trailing ‘S’ from ename) from emp;
–3.去除姓名两侧的S(造数测试)
select * from emp;
select trim(‘S’ from ename) from emp;
–4.去除姓名左侧的SM
select ltrim(ename,‘SM’) from emp;
select trim(leading ‘SM’ from ename) from emp;–

–5.去除姓名右侧的TH
select rtrim(ename,‘TH’) from emp;
select trim(trailing ‘S’ from trim(trailing ‘T’ from ename)) from emp;

–6.去除左右两侧的AB(造数测试)
select rtrim(ltrim(ename,‘AB’),‘AB’) from emp;
select trim(leading ‘B’ from trim(leading ‘A’ from trim(trailing ‘B’ from trim(trailing ‘A’ from ename)))) from emp;
–7.去除字符@@@@@左侧的@(原理)
select ‘@@@@@’,ltrim(’@@@@@’,’@’) from dual;
select ‘@@@@@’,ltrim(’@@@@@’,’@’) from dual;
select ‘@@@@@’,trim(leading ‘@’ from ‘@@@@@’) from dual;
select '@
@@@@’,trim(leading ‘@’ from ‘@@@@@’) from dual;
注意:虽然trim()、ltrim()、rtrim()都是又来去吃字符串当中的指定部分,但是完整用法上有很大区别,
一定要注意区分
1)rtrim(str[,s])、ltrim(str[,s])其中s可以是单个字符,也可以是多个字符,trim() 当中s只能是一个字符;
2)trim函数没有trim(str,s)的用法,ltrim()、rtrim()也没有ltrim(s from str) 的用法
3)三个函数在去除是都是从某测开始去除,知道第一个非s出现,特别需要注意的是ltrim()、rtrim()当中的s 是一个个检测,而不是看作一个整体,区别与replace
select ‘ABABBABAABCD’,ltrim(‘ABABBABAABCD’,‘AB’)from dual;–CD
select trim(both ‘A’ from ‘ABCDCBA’) from dual;–BCDCB 去头去尾
select trim(leading ‘A’ from ‘ABCDCBA’) from dual;–BCDCBA 去左
select trim(trailing ‘A’ from ‘ABCDCBA’) from dual;–ABCDCB 去右
select trim(‘A’ from ‘ABCDCBA’) from dual;–BCDCB 默认去头去尾

5. 截取

substr(str,ind[,len]) :从str当中的第ind 为开始截取,长度为len的字符 并返回字符内容
substr函数是聚合函数当中使用最频繁的,一定要记住
例子:
–截取
substr(str,ind[,len]):在str中ind位置开始 ,截取长度位len 的内容 返回
–1)截取字符串’ABCDEF’中的前三个字符
select substr(‘ABCDEF’,1,3) from dual;–ABC
–2)截取名字中的前两位字符
select ename,substr(ename,1,2) from emp;
–3)从名字中的第二位字符开始,截取三位长度
select ename,substr(ename,2,3) from emp;

–特殊举例
select ename,substr(ename,0,2) from emp;–第一位开始截取
select ename,substr(ename,-2,2) from emp;–WARD --RD
select ename,substr(ename,-1,2) from emp;–WARD --D
select ename,substr(ename,-2,0) from emp;–WARD
select ename,substr(ename,-2,-2) from emp;–WARD
select ename,substr(ename,2,100) from emp;–WARD–ARD
select ename,substr(ename,2) from emp;–WARD–ARD

总结:
1)截取函数当中的ind len 分别表示 启示位置和截取长度,而非起始位置和结束位置,需要注意区分
2)从0 位开始截取,相当于从1位开始截取
3)如果ind 是正书则表示从左道右开始定位,如果是负数则表示从右到左开始定位
4)无论ind是正数还是负数 都是从左到右开始截取
5)若len为0 或者负数则返回空值
6)若len的值大于str的长度则截取到最后
7)len可以省略,表示截取到最后,ind不可以省略

6. 填充

–填充
lpad(str,n,s):在str 左侧填充s,长度到达n
rpad()str,n,s) :在str 右侧填充s 长度达到n
–在名字左侧添加字符使总长度达到10
select ename, lpad(ename,10,’
’) from emp;–*****SMITH
–在名字右侧添加字符]使总长度达到10
select ename, rpad(ename,10,’]’) from emp;–SMITH]]]]]

总结:
1)填充函数不常用,但是非常重要 ,要知道有这个函数
2)s可以是单个字符,又可以是字符串,如果s是字符串填充是则循环使用s当中的每一个字符
3)填充的步骤是先计算达到n长度需要多少个字符,然后用s字符串拼接成对应的字符,附到目标字符的左侧或者右侧
4)尽量避免n比str长度还有小的情况

总结:针对字符串的处理,返回值仍然是字符串的函数
select concat(concat(ename,deptno),job) from emp;–连接
select ename,initcap(upper(lower(ename))) from emp; --大小写
select replace(‘ABCD’,‘A’,‘a’) from dual;–替换
select trim(‘A’ from ‘ABABBACD’) from dual;–BABBACD 去除
select ‘ABCDCBA’,substr(‘ABCDCBA’,1,3) from dual;–ABCDCBA–ABC 截取
select ename,lpad(ename,10,’%’) from emp;–AAAAA–%%%%%AAAAA 填充

 针对字符、且返回值是数值的函数
7. 获取字符长度
lenth(str) :返回字符串字符的长度
lenthb(str):返回字符串的字节长度
–1)求字符串’ABCDE’的长度
select length(‘ABCDE’) from dual;–5
–2)求每个员工姓名的长度
select ename,length(ename) from emp;
–3)求姓名总共有五个字符的员工
select ename from emp where ename like ‘_____’;
select ename from emp where length(ename) = 5;
–4)求姓名总共有五位、且首字母是A的员工
select ename from emp where ename like ‘A____’;
select ename from emp where substr(ename,1,1) = ‘A’;
–5)将员工按照姓名长度分组,计算每个分组的人数,并按长度升序排列
select length(ename) 长度, count(*)
from emp
group by length(ename)
order by length(ename);
–6)查询字符串’小猪佩奇’的长度
select length(‘小猪佩奇’) from dual; --4
select lengthb(‘小猪佩奇’) from dual;–8
–7)录入员工信息:1000号员工’小猪佩奇’
select * from emp where ename = ‘小猪佩奇’;

–查看字符集
select * from nls_database_parameters where parameter = ‘nls_characteraet’;
事实上,所谓长度是指字符长度,而字段属性所设置的长度是指字节长度,英文符号、数字、字母 一个字节组成一个字符,但是中文符号和汉字不确定。
具体一个字符有多少个字节组成,由数据库的字符集设置决定
字符集与字符字节的关系:
UTRF-8:一个汉字占三个字节–常用
ZHS16GBK:一个汉字占两个字节 --常用
WE8ISO88S9PI:一个汉字占一个字节–罕见
如何直观的判断字节长度?
lengthb(str):返回字符串字节长度
select ‘小明’,length(‘小明’),lengthb(‘小明’) from dual;-2, 4
所有函数当中以b结尾多是关于字节的函数

8. 获取字符位置

instr(str,s,[ind],[n]):从第ins位开始 查找s在str中第n 次出现的位置
一般用法:
instr(str,s) :从第一位开始查询s在str中第一次出现的位置
select instr(‘ABCDCBA’,‘B’) from dual;–2
select instr(‘ABCDCBA’,‘CD’) from dual;–3
select instr(‘ABCDCBA’,‘CF’) from dual;–0
select instr(‘ABCDEF’,‘B’,3) from dual;–0
select instr(‘ABCDEFABCDEF’,‘B’,3) from dual;–8
select instr(‘ABCDEFABCDEF’,‘BC’,3) from dual;–8
select instr(‘ABCDEFABCDEF’,‘BC’,2) from dual;–2
select instr(‘ABCDEFABCDEF’,‘B’,2,2) from dual;–8
总结:
1)若s指当字符这返回该字符所在位置,若s是字符串,则返回首字母所在的位置
2)若s是字符串,查找是将s视为整体,若strs当中不存在时则返回0
3)无论从哪里开始找i,返回时都是从第一位开始返回

思考题:
1.求名字中至少有两个A的员工
select * from emp where ename like ‘%A%A%’ ;
select * from emp where instr(ename,‘A’,1,2)!= 0 or instr(ename,‘A’,1,3) > 0;

2.求名字中正好有两个A的员工
select * from emp where ename like ‘%A%A%’ and ename not like ‘%A%A%A%’;
select * from emp where instr(ename,‘A’,1,2)!=0 and instr(ename,‘A’,1,3)=0 ;

–深入研究
–1)ind = 0
select instr(‘ABCDEF’,‘B’,0) from dual;–0
–2)ind < 0
select instr(‘ABCDEF’,‘B’,-2) from dual;–2
select instr(‘ABCDEFABCDEF’,‘B’,-4,2) from dual;–2
select instr(‘ABCDEFABCDEFABCDEF’,‘B’,-4,3) from dual;–2
select instr(‘ABCDEFABCD’,‘B’,-5) from dual;–2
–3) 超过 字符长度
select instr(‘ABCDEF’,‘B’,10) from dual;–0

–4) n <= 0
select instr(‘ABCDEF’,‘B’,1,0) from dual;–报错 n 不能写0
select instr(‘ABCDEF’,‘B’,1,-2) from dual;–报错 n 不能写负数

–5) n 超过字符串中出现的次数
select instr(‘AABCCDD’,‘B’,1,3) from dual;–0
再次总结:
1)ind = 0 返回0
2)ind <0 代表从右侧开始数 第n 次s出现的位置,返回位置仍然时从左侧开始算起
3)ind 超出str长度 返回0

  1. n <= 0 报错
    5) n 超过str长度,返回 0
    6)ind 和 n 都是小数 按照整数部分运行

三、数值型函数

  1. 取绝对值
  2. 向上取整与向下取整
  3. 取余
  4. 四舍五入
  5. 截断
1、取绝对值

abs(num) : 获取num对应的绝对值
该函数通常不直接对某数取绝对值,而是对一系列的计算结果获取绝对值
–绝对值
select abs(123.45),abs(-123.45) from dual;
select sal,comm,sal-comm,abs(sal-comm) from emp;

2、向上取整与向下取整

–ceil 向上取整
select (num) :向上取整,获取离num最近的两个整数当中比较大的那个数
select ceil(5.5) from dual;–6
select ceil(1.2) from dual;–2
select ceil(-1.2)from dual;–(-1)
–floor(num): 向下取整, 获取离num最近的两个整数当中较小的那个数
select floor(5.5) from dual;–5
select floor(1.2) from dual;–1
select floor(-1.2) from dual;–(-2)
select floor(6) from dual;–6
注意:
1)若num本身就是整数,无论是向上取整还是像下取整,返回值结果就是整数本身
2) 无论num是负数还是正数,所谓上,即数轴只想的方向,所谓下,即是数轴背向的方向

3、取余

–取余
mod(x,y):x/y取余
select mod(13,5) from dual;–3
select mod(-14,5) from dual;–(-4)
select mod(13,-5) from dual;–(-3)
select mod(-14,-5) from dual;–(-4)

4、四舍五入

–四舍五入
round(num[,p]) : 对数值num 进行四舍五入,取整参数p决定四舍五入的精度
–基础用法
select round(4.5321,2),round(4.56789,2) from dual;–4.53–4.57
–精度为0或者精度省略
select round(4.5321,0),round(4.54321) from dual;–5--5
–负数四舍五入
–先取绝对值,再四舍五入 然后在前面加负号
select round(-1.4),round(-1.6) from dual;–(-1)–(-2)
–精度为负数
select round(4.5321,-1),round(45.321,-2),round(55.321,-2),round(55.321,-3) from dual;–0--0–100–00
–精度不为整数
–按照整数部分处理
select round(5.4321,2.222),round(5.4321,2.99999) from dual;–5.43–5.43

5、截断

–截断
trunc(num[,p]):对num进行截断,p决定了截断的精度
–基础用法
select trunc(4.5321,2),trunc(4.56789,2) from dual;–4.53–4.56
–精度为0或精度省略
select trunc(4.5321,0),trunc(4.5321) from dual;–4--4
–负数的截取
select trunc(-1.4),trunc(-1.6) from dual;–(-1)–(-1)
–精度为负数
select trunc(45.321,-1),trunc(145.321,-2),trunc(155.321,-2),trunc(1155.321,-3) from dual;–0--100-100-1000
–精度不为整数
select trunc(5.4321,2.2222),trunc(5.4321,2.99999) from dual;–5.43–5.43

四、日期型函数

1.关于日期的四舍五入与截断
2.获取月份差值
3.获取月末日期
4.月份加减
5.获取下个周几
–关于日期的计算:日期直接加减一个整数,该数值以天为单位
select sysdate-1 from dual;–减一天
select sysdate-1/24 from dual;–减一个小时
select sysdate-1/24/60 from dual;–减一分钟

1.关于日期的四舍五入与截断

round()函数与 trunc()函数除了可以作用在数值上,也可以作用在日期上,对于日期也同样有四舍五入或截断的需求
对于四舍五入,在数值方面依靠数值5作为分界线,达不到5即被舍去,达到5即向前进1。在日期方面,四舍五入同样需要一个分界线,该分界线在不同的时间单位中并不相同,原则上是取居中的位置作为分界线。
对于截断,日期的截断与数值的截断类似,定位到截取精度,直接舍弃精度之外的部分,留下精度之内的部分。
1.省略精度,即默认的精确到天,天的界限
2.年的界限
3.月的界限
4.季的界限
5.小时的界限
6.星期的界限
–省略精度,默认精度为天 天的界限 12:00:00
select to_date(‘20220404 11:59:59’,‘YYYYMMDD HH24:MI:SS’),–2021/04/04 11:59:59
round(to_date(‘20220404 11:59:59’,‘YYYYMMDD HH24:MI:SS’)),–2021/04/04
round(to_date(‘20220404 12:00:00’,‘YYYYMMDD HH24:MI:SS’)),–2021/04/05
round(to_date(‘20220404 12:00:01’,‘YYYYMMDD HH24:MI:SS’)),–2021/04/05
trunc(to_date(‘20220404 12:00:00’,‘YYYYMMDD HH24:MI:SS’))–2021/04/04
from dual;
–年的界限:7月
select round(to_date(‘20220630’,‘YYYYMMDD’),‘YYYY’),–2022/01/01
round(to_date(‘20220701’,‘YYYYMMDD’),‘YYYY’),–2023/01/01
round(to_date(‘20220624’,‘YYYYMMDD’),‘YYYY’),–2023/01/01
trunc(to_date(‘20220630’,‘YYYYMMDD’),‘YYYY’)2023/01/01
from dual;

–月的界限:16号
select round(to_date(‘20220614’,‘YYYYMMDD’),‘MM’),–2022/06/01
round(to_date(‘20220615’,‘YYYYMMDD’),‘MM’),–2022/06/01
round(to_date(‘20220616’,‘YYYYMMDD’),‘MM’),–2022/07/01
round(to_date(‘20220215’,‘YYYYMMDD’),‘MM’),–2022/02/01
round(to_date(‘20220216’,‘YYYYMMDD’),‘MM’),–2022/03/01
trunc(to_date(‘20220617’,‘YYYYMMDD’),‘MM’)–2022/06/01
from dual;
–季度界限 :中间月份的16号 ,达到该标准,季度加一 返回对应季度的第一天
select round(to_date(‘20220614’,‘YYYYMMDD’),‘Q’),–2022/07/01
round(to_date(‘20220615’,‘YYYYMMDD’),‘Q’),–2022/07/01
round(to_date(‘20220616’,‘YYYYMMDD’),‘Q’),–2022/07/01
round(to_date(‘20220215’,‘YYYYMMDD’),‘Q’),–2022/01/01
round(to_date(‘20220216’,‘YYYYMMDD’),‘Q’),–2022/04/01
trunc(to_date(‘20220317’,‘YYYYMMDD’),‘Q’)—2022/01/01–直接截取对应季度,返回当季度第一天
from dual;
–小时的界限 :30分
select to_date(‘20220404 11:59:59’,‘YYYYMMDD HH24:MI:SS’),–2021/04/04 11:59:59
round(to_date(‘20220404 12:29:59’,‘YYYYMMDD HH24:MI:SS’),‘HH24’),–2021/04/04 12:00:00
round(to_date(‘20220404 12:30:00’,‘YYYYMMDD HH24:MI:SS’),‘HH24’),–2021/04/05 13:00:00
round(to_date(‘20220404 12:31:01’,‘YYYYMMDD HH24:MI:SS’),‘HH24’),–2021/04/05 13:00:00
trunc(to_date(‘20220404 12:40:00’,‘YYYYMMDD HH24:MI:SS’),‘HH24’)–2021/04/0412:00:00
from dual;
–星期的界限:周四中午12点
select round(to_date(‘20220404’,‘YYYYMMDD’),‘IW’),-- 星期一2022/04/04
round(to_date(‘20220405’,‘YYYYMMDD’),‘IW’),–星期二2022/04/04
round(to_date(‘20220406’,‘YYYYMMDD’),‘IW’),–星期三2022/04/04
round(to_date(‘20220406 11:59:59’,‘YYYYMMDD HH24:MI:SS’),‘IW’),–星期三2022/04/04
round(to_date(‘20220406 12:00:00’,‘YYYYMMDD HH24:MI:SS’),‘IW’),–星期三2022/04/04
round(to_date(‘20220407 11:30:00’,‘YYYYMMDD HH24:MI:SS’),‘IW’),–星期四2022/04/04
round(to_date(‘20220407 12:00:01’,‘YYYYMMDD HH24:MI:SS’),‘IW’),–星期四2022/04/11
round(to_date(‘20220407’,‘YYYYMMDD’),‘IW’),–星期四2022/04/04
round(to_date(‘20220408’,‘YYYYMMDD’),‘IW’),–星期五2022/04/11
round(to_date(‘20220409’,‘YYYYMMDD’),‘IW’)–星六2022/04/11
from dual;

2、获取月份差值

months_bewteen(d1,d2) :d1,d2之间相差几个月(d1>d2)
常规用法:给定L两个日期,计算两个日期之间的月份差
–1)计算从元旦到今天经过了几个月(整数月)
select to_date(‘20220107’,‘YYYYMMDD’) from dual;–2022/01/07
select to_date(‘20220101’,‘YYYYMMDD’) from dual;–2022/01/01
select months_between(to_date(‘20220107’,‘YYYYMMDD’),to_date(‘20220101’,‘YYYYMMDD’)) from dual;–0.193548387096774
select (7-1)/31 from dual;–0.193548387096774
select ceil(months_between(to_date(‘20220107’,‘YYYYMMDD’),to_date(‘20220101’,‘YYYYMMDD’))) from dual;–1
select round(months_between(to_date(‘20220107’,‘YYYYMMDD’),to_date(‘20220101’,‘YYYYMMDD’))) from dual;–0
select trunc(months_between(to_date(‘20220107’,‘YYYYMMDD’),to_date(‘20220101’,‘YYYYMMDD’))) from dual;–0
select floor(months_between(to_date(‘20220107’,‘YYYYMMDD’),to_date(‘20220101’,‘YYYYMMDD’))) from dual;–0

–2)计算从元旦到今天经过了几个月(非整数月)
select months_between(to_date(‘20220107’,‘YYYYMMDD’),to_date(‘20220101’,‘YYYYMMDD’)) from dual;–0.193548387096774

–3)计算从今天到明年元旦还要等待几个月(整数月)
select to_date(‘20220107’,‘YYYYMMDD’),–2022/01/07
to_date(‘20230101’,‘YYYYMMDD’),–2023/01/01
months_between(to_date(‘20230101’,‘YYYYMMDD’),to_date(‘20220107’,‘YYYYMMDD’)),–11.8064516129032
round(months_between(to_date(‘20230103’,‘YYYYMMDD’),to_date(‘20220107’,‘YYYYMMDD’)))–12
from dual;
–25=2022/12/07-2023/01/01
select 25/31 from dual;–0.806451612903226

select months_between(to_date(‘20230201’,‘YYYYMMDD’),to_date(‘20230301’,‘YYYYMMDD’)) from dual;–(-1)
特殊情况:

–特殊情况
–1)一般工作中使用到的情况是,给定两个月初或月末日期、或者两个DD相同的日期,返回的是整数。
select months_between(to_date(‘20220201’,‘YYYYMMDD’),to_date(‘20220101’,‘YYYYMMDD’)) from dual;–1
select months_between(to_date(‘20220228’,‘YYYYMMDD’),to_date(‘20211231’,‘YYYYMMDD’)) from dual;–2
select months_between(to_date(‘20220208’,‘YYYYMMDD’),to_date(‘20211208’,‘YYYYMMDD’)) from dual;–2
select months_between(to_date(‘20220228’,‘YYYYMMDD’),to_date(‘20220128’,‘YYYYMMDD’)) from dual;–1
–如果给定的两个日期DD不相同,月份差会得到非整数,小数部分为剩余天数/31,这个规则无论针对哪一个月都是如此;
select months_between(to_date(‘20220328’,‘YYYYMMDD’),to_date(‘20220320’,‘YYYYMMDD’)) from dual;–0.258064516129032
select 8/31 from dual;–0.258064516129032
–2)如果SELECT MONTHS_BETWEEN(TO_DATE(‘20220107’,‘YYYYMMDD’),TO_DATE(‘20211207’,‘YYYYMMDD’)) FROM DUAL;
–给定的两个日期DD不同,但是想要获得整数月,可以配合TRUNC函数或后续提到的获取月末日期函数使用;
–3)如果两个日期的DD不同,但是都是月末日期,则获取的月份差将是整数;
–4)需要特别注意,函数中录入的两个日期是有大小之分的(区别BETWEEN AND),一般晚的日期在前,早的日期在后,如此得到的结果便是正数,反之获得负数。如果不确定两个日期的大小,可搭配ABS()函数使用。

3、获取月末日期

last_day(d) :获取获取指定日期对应的当月最后一天,即月末日期
例子:
select last_day(to_date(‘20240204’,‘YYYYMMDD’)) from dual;–2024/02/29
–获取当月最后一天
select sysdate,systimestamp,last_day(sysdate) from dual;–2022/01/31 11:18:03
–查询某月份的最大天数
select last_day(to_date(‘20240804’,‘YYYYMMDD’)) from dual;–2024/08/31
–获取给定两日期的月份差(整数月)
select last_day(to_date(‘20240804’,‘YYYYMMDD’)),–2024/08/31
last_day(to_date(‘20240804’,‘YYYYMMDD’)),–2024/08/31
months_between(last_day(to_date(‘20240804’,‘YYYYMMDD’)),last_day(to_date(‘20240204’,‘YYYYMMDD’)))–6
from dual;

4、月份加减

ad_months(d,n) :在d的日期上加上n个月,n可以是负数
–月份加减
–基础用法
select sysdate,add_months(sysdate,2) from dual;
select sysdate,add_months(sysdate,-2) from dual;–减两个月
–n 为负数,即在日期d的基础上减去n个月

–特殊情况
–1)n 是小数 --按照整数部分处理
select add_months(to_date(‘20220202’,‘YYYYMMDD’),1.2) from dual;–2022/03/02
select add_months(to_date(‘20220202’,‘YYYYMMDD’),1.5) from dual;–2022/03/02
select add_months(to_date(‘20220202’,‘YYYYMMDD’),1.8) from dual;–2022/03/02
–2)如果d是月末,无论加减几个月,返回结果都是该月的月末
select add_months(to_date(‘20220131’,‘YYYYMMDD’),1) from dual;–2022/02/28
select add_months(to_date(‘20220228’,‘YYYYMMDD’),-1) from dual;–2022/01/31
–3)如果d不在计算的月份里面,返回结果是该月的月末
select add_months(to_date(‘20220130’,‘YYYYMMDD’),1) from dual;–2022/02/28

–思考 : 返回日期当月最后一天
select to_date(‘20220107’,‘YYYYMMDD’),–2022/01/07
last_day(to_date(‘20220107’,‘YYYYMMDD’)),–2022/01/31
add_months(last_day(to_date(‘20220107’,‘YYYYMMDD’)),-1),–2021/12/31
add_months(last_day(to_date(‘20220107’,‘YYYYMMDD’)),-1)+1 from dual;–2022/01/01

select trunc(to_date(‘20220107’,‘YYYYMMDD’),‘MM’) from dual;–2022/01/01
select round(to_date(‘20220107’,‘YYYYMMDD’),‘MM’) from dual;–2022/01/01
select to_char(‘20220107’,‘YYYY/MM’) from dual;

5、获取下个周几

next_day(d,w):给定日期d,星期几w,获取日期d的下个星期w
–获取下个星期几
select to_char(to_date(‘20220107’,‘YYYYMMDD’),‘DAY’) from dual;–星期五
select next_day(to_date(‘20220107’,‘YYYYMMDD’),‘星期五’) from dual;–2022/01/14
select to_char(to_date(‘20220114’,‘YYYYMMDD’),‘DAY’) from dual;–星期五
–思考题:
–给定任意日期,如何获取下个周的星期五
select to_date(‘20220107’,‘YYYYMMDD’),–2022/01/07
trunc(to_date(‘20220107’,‘YYYYMMDD’),‘IW’),–2022/01/03 找到本周第一天 星期一
trunc(to_date(‘20220107’,‘YYYYMMDD’),‘IW’)+5,–2022/01/08 星期六
next_day(trunc(to_date(‘20220107’,‘YYYYMMDD’),‘IW’)+5,‘星期五’)–下个星期五
from dual;

select next_day(to_date(‘20220107’,‘YYYYMMDD’),‘星期五’) from dual;–2022/01/14

–1.将所有员工的名字按小写的方式显示。
select lower(ename) from emp;
–2.显示所有员工姓名的前三个字符。
select substr(ename,1,3) from emp;
–3.显示正好为5个字符的员工的姓名。
select ename from emp where ename like ‘_____’;
–4.以首字母大写,后面小写的方式显示所有员工的姓名。
select initcap(ename) from emp;
–5.以首字母小写,后面大写的方式显示所有员工的姓名。
select lower(substr(ename,1,1))||upper(substr(ename,2)) from emp;
–6.以首字母大写,中间小写,末尾字母大写的方式显示所有员工的姓名。
select upper(substr(ename,1,1))||lower(substr(ename,2,length(ename)-2))||upper(substr(ename,length(ename)-1,1)) from emp;
–7.显示所有员工的姓名,用“我是老虎”替换所有“A”
select replace(ename,‘A’,‘我是老虎’) from emp;
–8.显示薪水的时候,把本地货币单位加在前面
select to_char(sal,‘L99999.99’) from emp;
–9.显示1982年和1987年入职的所有员工
select * from emp where to_char(hiredate,‘YYYY’) = 1982 or to_char(hiredate,‘YYYY’) = 1987;
—10.显示所有10月份入职的员工
select * from emp where to_char(hiredate,‘MM’) = 10;
–11.以字符长度为10的方式显示员工职位,多余的位数在以来填充
select rpad(job,10,’
’) from emp;
–12.找出字符串“oracle training”中第二个ra出现的位置
select instr(‘oracle training’,‘ra’,1,2) from dual;–9
–13.去除字符串“ aadde gf ”两边的空格
select trim(’ aadde gf ‘) from dual;
–14.以指定格式显示员工的工资(格式:SMITH 的工资是 800)
select ename||’ 的工资是 '||sal from emp;
–15.显示所有员工的姓名,用a替换所有"A"
select replace(ename,‘A’,‘a’) from emp;
–16.显示员工姓名中包含“H”的员工
select ename from emp where ename like ‘%H%’;
–17.显示员工姓名中第二个字符是“L”的员工
select ename from emp where ename like ‘_L%’;
–18.显示员工姓名中最后一个字符是“T”的员工
select ename from emp where ename like ‘%T’;
–19.显示所有员工的姓名、加入公司的年份和月份,并且按照年份升序排列
select ename,to_char(hiredate,‘YYYY/MM’) from emp order by to_char(hiredate,‘YYYY’);
–20.查询当前日期(精确到秒)
select systimestamp from dual;
–21.显示员工工资,加上$
select ‘$’||sal from emp;
–22.将字符串"1980-12-17"转成日期
select to_date(‘1980-12-17’,‘YYYY-MM-DD’) from dual;
–23.求入职最早员工和入职最晚员工的入职日期
select to_date(min(to_number(to_char(hiredate,‘YYYYMMDD’))),‘YYYYMMDD’),to_date(max(to_number(to_char(hiredate,‘YYYYMMDD’))),‘YYYYMMDD’) from emp;
–24.求名字中至少有两个A的员工
select * from emp where ename like ‘%A%A%’;

学习笔记,仅供参考!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

li星野

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值