oracle学习之基本查询和条件过滤,分组函数使用

Posted *平凡*随风舞

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了oracle学习之基本查询和条件过滤,分组函数使用相关的知识,希望对你有一定的参考价值。

oracle是殷墟出土的甲骨文的第一个单词,所以在中国叫做甲骨文,成立于1977年,总部位于美国加州。

在安装好后,主要有两个服务需要开启:

1,实例服务,OracleServiceORCL,决定是否可以连接上数据库

2,监听服务,OracleOraDb11g_home1TNSListener,决定是否可远程连接数据库

在安装好客户端后,登录方式:

sqlplus 用户名/密码

如果是远程登录,需要加上连接别名,或者IP:

sqlplus 用户名/密码@//IP地址/实例名
or
sqlplus 用户名/密码@连接名

数据库基本查询:

select * from tab;

tab是一个数据字典,字义了当前用户有哪些表,以及类型,查看表结构:

desc dept

  注意,如果显示行大小和宽度不正确,可以通过修改登录设置文件改变:

路径:\\app\\Administrator\\product\\11.2.0\\client_1\\sqlplus\\admin
set linesize 140;//设置行大小
set pagesize 120;//设置页宽度
col empno for 99999;//修改数值型字段长度
col ename for a20;//设置字符型字段长度

  sql语法的注意事项:关键字不能缩写,不能换行,以分号结尾!

查看sqlplus的所有命令:

? topic

查询SQL语句语法:

select [distinct]*|column_name|expr|alias from tablename

 查询员工号,姓名,月薪,奖金,年薪:

注意,奖金字段有为null的结果,可以通过虑空函数解决,即:nvl(a,b),如果a为null,返回b,否则返回a

如果需要查看员工表不同的部门编号,并且去除重复的,可以这么做:

通常,我们还可以借助伪表来进行一些的数学计算或函数操作:

select 3+20*5,sysdate from dual;

  比较运算符的查询条件过滤: = != <> < > <= >= (between and)

case1: 查询入职日期为1981年11月17日的员工信息:

select * from emp where hiredate = \'1981-11-17\'

  这里要注意,如果显示文字与格式字符串不匹配的问题,通常必须按照具体日期格式写:

如果自己想修改这个日期格式,可以进入管理员用户后修改,如下:

SQL> select sysdate from dual;
//修改会话日期格式
SQL> alter session set nls_date_format=\'yyyy-mm-dd\';
//后面就可以这样查询了:
SQL> select * from emp where hiredate =\'1981-11-17\';

  逻辑运算符 and or not,这里特别说明一下,查找工资在1000~2000的员工信息:

select * from emp where sal >= 1000 and sal <= 2000;
//或者
select * from emp where sal between 1000 and 2000;

  between and 是属于闭区间,从小到大!

如何正确查询奖金为空的员工信息 - null

select * from emp where comm is null;

  当and or 存在多个条件写,如何来写才更优?

sql语句是从右到左执行,and情况,应该将易假的放在右侧,or情况,应该将真的放在右侧。

like ->模糊查询,\'%\'匹配任意多个字符,\'_\'匹配任意一个字符

重点:查询带在下划线\'_\'的应该怎么查询:

select * from emp where ename like \'%/_%\' escape \'/\';

  排序:group by; having; order by;语法如下:

order by col|expr|alias|number

  员工薪水按从大到小排序(序号)

select * from emp order by sal desc;
//或者
select * from emp order by 6 desc;
//或者
select empno,ename,job,mgr,sal,comm,deptno from emp order by 5 desc;

  这里更要注意null的情况,默认无穷大:

解决办法是:

select * from emp where deptno = 30 order by comm desc nulls last;
//或者
select * from emp where deptno = 30 order by nvl(comm,-1) desc;

  oracle的单行函数:

什么叫单行函数,即对一行进行变换,只产生一个结果。

lower(小写),upper(大写),initcap(首字母大写),||(可以进行字符串连接)

select lower(\'hello WorLD\') one,upper(\'HeLLo woRld\') two,initcap(\'hello WOrld\') from dual;
select \'aaaa\'||\'bbbb\'||\'cccc\' from dual;

  substr(字符串,位置,长度),从位置开始截取长度,长度可以省略,代表截取到未尾:

select substr(\'helloworld\',1,3) one,substr(\'helloworld\',1) two ,substr(\'helloworld\',-3) three from dual;

  length求字符串长度,lengthb求字节长度:

instr(str1,str2) ,判断str2是否在str1中,如果存在返回出现的首位置,否则返回0:

select instr(\'hello world\',\'llo\') from dual;

  lpad,rpad,左右填充l(r)pad(str,len,char) 返回len长度的字符串,如果str不够长度,则是char字符填充:

select lpad(\'hello\',10,\'#\') from dual;

  trim(str)去首尾空格,replace(str,substr,strto)替换

select \'aaa\'||trim(\' hello world \')||\'bbb\' from dual;

  还能这么玩:

重要:数值函数,round四舍五入,trunc截断,mod取模

select round(45.926, 2) 一, round(45.926, 1) 二, round(45.926, 0) 三,  round(45.926, -1) 四, round(45.926, -2) 五 from dual;
select trunc(45.926, 2) 一, trunc(45.926, 1) 二, trunc(45.926, 0) 三,  trunc(45.926, -1) 四, trunc(45.926, -2) 五 from dual;
select mod(600,1000),mod(1000,600) from dual;
//ceil 和floor 向上取整,向下取整 
select ceil(121/60),floor(121/60) from dual;

 重要:转换函数,to_char,to_number,to_date 

 

 把薪水转换为本地货币字符型:

select sal,to_char(sal,\'L9,999\') from emp;

如果要将这个在转回数值型,语句是一样的:

select to_number(\'¥1,250\',\'L9,999\') from dual;

  to_char 与 to_date 显示 \'yyyy-mm-dd hh24:mi:ss 今天是 星期几\'

select to_char(sysdate,\'yyyy-mm-dd hh24:mi:ss "今天是" day\') from dual;

  将上述字符串反转为日期:

select to_date(\'2017-11-10 15:48:13 今天是 星期五\',\'yyyy-mm-dd hh24:mi:ss "今天是" day\') from dual;

  此处可以解决一个隐式日期转换问题:

select * from emp where to_char(hiredate,\'yyyy-mm-dd\')=\'1981-11-17\';

 上面的能显示转换,尽量显示转换。

重要:日期函数,months_between add_months last_day next_day

1,显示昨天,今天,明天:

select sysdate-1 昨天,sysdate 今天,sysdate+1 明天 from dual;

  2,计算员工工龄,可以按日,周,月,年,日期差减方法

select months_between(sysdate,to_date(\'2017-10-10\',\'yyyy-mm-dd\')) from dual;

  3,求明年的今天:

select add_months(sysdate,12) from dual;

  4,求指定日期所在月份最后一天

select last_day(sysdate) from dual;

  5,求指定日期的下一个星期几日期:

select next_day(sysdate,\'星期一\') from dual;

  条件表达示

CASE expr  WHEN comparison_expr1 THEN return_expr1
            [WHEN comparison_expr2 THEN return_expr2
            WHEN comparison_exprn THEN return_exprn
            ELSE else_expr]
END

  老板打算给涨工资,总裁1000,经理800,其它400,将涨前,涨后根据职业列出:

select empno,ename,job,sal 涨前薪水,case job when \'PRESIDENT\' then sal+1000
					when \'MANAGER\' then sal+800
					else sal+400
					end 涨后薪水
from emp

另外在oracle中,还可以使用decode函数,其它Sql不支持:

语法:decode(expr,search1,res1,search2,res2,…,default)
select empno,ename,job,sal 涨前薪水,decode(job,\'PRESIDENT\',sal+1000,\'MANAGER\',sal+800,sal+400) 涨后薪水 from emp

分组函数:avg,sum,min,max,count

1,求员工的工资总和:

select sum(sal) from emp;

2,求员工的总人数:

select count(empno),count(*) from emp;

3,求emp表中工种数:

4,求平均工资(三种方式):

 

分组数据:在select中出现的非组函数的列,必须在group by中出现

1,查询各部门平均工资:

select deptno,avg(sal) from emp group by deptno;

2,查询各部门,各工种平均工资:

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

3,查询平均薪水大于2000的部门:

select deptno,avg(sal) from emp group by deptno having avg(sal)>2000;

4,求10号部门员工的平均薪水:

select deptno,avg(sal) from emp where deptno=10 group by deptno;

  此处注意,第3和第4条,where后不能放分组函数,deptno不是,所以可以在where后

 where 是先过滤,后分组,having是先分组后过滤,所以相对来说where要好些。

常见的非法使用组函数情况:

 

最后对null进行一个总结:

1,null不能用 = 或者 !=,应该使用 is

2,not in的集合中不能有null

3,null无穷大,默认排在最前

4,表达式中null参与运算,结果为null,应使用nvl(a,b)

5,分组函数会自动过滤null

  

  

  

以上是关于oracle学习之基本查询和条件过滤,分组函数使用的主要内容,如果未能解决你的问题,请参考以下文章

Mysql的基本查询语句

Oracle数据库,模糊查询去重查询

oracle分组查询

oracle分组查询

Oracle学习之简单查询语句

oracle查询与函数