前言
必读在前言这我们先了解下查询的基本情况,这是一篇关于查询的文章,你想要知道的查询知识都在这!如果嫌文章字多,可以根据目录跳转快速阅读!!!
查询是数据的一个重要操作。用户发送查询请求,经编译软件变异成二进制文件供服务器查询,后返回查询结果集给用户,查询会产生一个虚拟表,看到的是表形式显示的结果,但结果并不真正的存储,每次执行查询只是从数据表中提取数据,并按照表的形式显示出来。
select {[distinct | all ] columns | *} //<列名>
[into table_name]
from {table | views | other selects} //<表名>
[where conditions] //<查询条件表达式>
[group by columns] //<分组表达式>
[having columns] //<分组查询表达式>
[order by columns] //<排序的列名> [ASC或DESC]
执行过程:from–where – group by– having– select-- order by
- select子句:用于选择数据表、视图中的列。
- into子句:用于将原表的结构和数据插入新表中。
- from子句:用于指定数据来源,包括表、视图和其他select语句。
- where子句:用于对检索的数据进行筛选。
- group by子句:用于对检索结果进行分组显示。
- having子句:用于从使用group by 子句分组后的查询结果中筛选数据行。
- order by子句:用于对结果集进行排序(包括升序和降序)
(对分组查询的结果进行过滤,要使用having从句。having从句过滤分组后的结果,它只能出现在group by从句之后,而where从句要出现在group by从句之前。where过滤行,having过滤分组。having支持所有where操作符。)
选择列
选择表中的列组成结果表,通过select语句的select子句来表示。
查询所有的列
语法:select * from dept;
例: select * from dept; 也可以指定多个表 select * from dept,emp;
这里是说查询这个表中的所有列。
查询指定的列
语法: select 列名 from 表名;
例: select empno from emp; 也可以指定多个列 select empno,ename,job from emp;
这里指定多个列是可以改变列在查询结果中的默认显示顺序的。
为列指定别名
语法: select 列名 as "别名" from 表名;
例: select empno as "员工编号",ename as "员工姓名",job as "职务" from emp;
在为列指定别名时,关键字AS是可选项,也可以在列名后直接写别名。如 empno 员工编号
计算列值
在使用select语句时,对于数字数据和日期数据都可以使用算术表达式,在select语句中可以使用算术运算符,包括加减乘除和括号,另外在select语句中不仅可以执行单独的数学运算,还可以执行单独的日期运算以及列名关联的运算。
select sal*(1+0.1),sal from emp;
检索EMP表的sal列,把其值调整为原来的1.1倍。
消除结果集中的重复行
select job from emp;❶
select distinct job from emp;❷
如此使用distinct关键字可以去除结果集中重复的数据,该关键字用在select子句的列表前面。
选择行
选择行通过where指定条件实现,该子句必须紧跟在from子句之后。
表达式比较
比较运算符用于比较两个表达式的值,共有7个分别是=(等于)、<(小于)、<=(小于等于)、>(大于)、>=(大于等于)、<>(不等于)、!=(不等于)。当两个表达式值均不为空值(NULL)时,比较运算返回逻辑值TRUE(真)或FALSE(假),而当两个表达式中有一个为空值或都为空值时,比较运算将返回UNKNOWN。
例: select empno,ename,sal from emp where sal > 1500;
在SCOTT的模式下查询eMP表中工资(sal)大于1500的数据记录.
模糊查询——like
LIKE用于指出一个字符串是否与指定的字符串相匹配,其运算对象可以是char,varchar2和date类型的数据,返回逻辑值true或false,LIKE运算符可以使用以下两个通配符
- “%”代表0或多个字符。
- “_”代表一个且只能是一个字符。
select empno,ename from emp where ename like 'S%';
例如:“S%”表示以字母S开头的任意长度的字符串,“%M%”表示包含字母M的任意长度的字符串,“_MRKJ”表示5个字符长度,且后面4个字符是MRKJ的字符串。
tips:
可以在LIKE关键字前面加上NOT,表示否定的判断,如果LIKE为真,则NOT LIKE为假
范围比较
IN关键字
在测试一个数据是否匹配一组数据中的一个值时,用IN或NOT IN关键字来指定搜索条件
例1: select empno,ename job from emp where job in ('PRESIDENT','MANAGER');
在emp表中,用in查询职务为'PRESIDENT','MANAGER'中任意一种的员工信息。
例2: select empno,ename job from emp where job not in ('PRESIDENT','MANAGER');
在emp表中,用 not in查询职务不在指定目标列表'PRESIDENT','MANAGER'范围内的员工信息。
BETWEEN关键字
需要返回某一个数据值是否位于两个给定的值之间,可以使用范围条件进行检索,通常使用between …and 和not between …and来指定范围条件。
- 使用between …and查询条件时指定的第1个值必须小于第2个值,因为between …and实质是查询条件“大于等于第1个值,并且小于等于第2个值”的简写形式。即between …and包括两端的值等价与比较运算符的(>=…<=)
- 使用not between …and返回某一个数据值在两个指定值的范围以外,不包括两端的值
例1: select empno,ename,sal from emp where sal between 2000 and 3000;
在eMP表中使用 between and关键字查询工资(sal)在2000~3000元之间的员工信息.
例2: select empno,ename,sal from emp where sal not between 2000 and 3000;
在eMP表中使用 not between and关键字查询工资(sal)不在2000~3000元之间的员工信息.
空值比较
首先说明
空值:不存在的值 ≠ 空字符串:长度为0的字符串
空值代表的是未知的值,并不是所有的空值都相等,比如“student”表中有两个学生的年龄未知,但是无法证明这两个学生的年龄相等,这样就不能用“=”运算符来检验空值,这里用IS NULL关键字检测特殊值之间的等价性,IS NULL关键字通常在where子句中使用。
例: select empno,ename,comm from emp where comm is null;
查询emp表中没有奖金的员工信息。
子查询!!!
Oracle子查询就是嵌套查询,他把select 查询的结果作为另外一个select、update或delete语句的条件,它的本质就是where条件查询中的一个条件表达式。比如说,判定列值是否与某个查询的结果集中的值相等,作为查询条件一部分的查询称为子查询,PL/SQL允许select多层嵌套使用,用来表示复杂的查询。简单理解就是嵌套,嵌套,嵌套。Insert,update,delete,select语句都可以使用子查询。
子查询通常与IN , EXIST 和 比较运算符结合使用。其中我们数据库开发过程中,子查询可以根据查询结果的行数的多少,可以区分为单行子查询和多行子查询。
-
单行子查询:向外部返回的结果为空或者返回一行。
-
多行子查询:向外部返回的结果为空、一行、或者多行。
单行子查询
单行子查询是指返回一行数据的子查询语句,当在where子句中引用单行子查询时,可以使用单行比较运算符(=,>,<,>=,<=,<>)。
例: select empno,ename,sal from emp
where sal > (select min(sal) from emp)
and sal < (select max(sal) from emp);
在emp表中查询既不是最高工资,也不是最低工资的员工信息。
注意:
- 如果内层子查询语句的执行结果为空值,那么外层where子句就始终不会满足条件,这样该查询的结果就必然为空值,因为空值无法参与比较运算。
- 在执行单行子查询时,要注意子查询的返回结果必须是一行数据,否则提示报错无法执行。另外子查询中也不能包含order by,如果要对数据进行排序的话,那么只能在外层查询语句中使用order by子句。
多行子查询
多行子查询是指返回多行数据的子查询语句,当在where子句中使用多行子查询时,必须使用多行比较符IN ANY ALL。
IN运算符
使用IN运算符时,外查询会和子查询结果集的每一个结果进行匹对,只有一个匹对上了,那么外查询就返回当前的检索的记录。
例: select empno,ename,job from emp
where deptno in (select deptno from dept where dept.dname <> 'SALES');
在emp表中查询不是销售部门的员工信息。
ANY运算符
ANY运算符必须与单行操作符结合使用,并且返回行只要匹配子查询的任何一个结果即可。
例: select deptno,ename,sal from emp
where sal > any
(select sal from emp where deptno = 10) and deptno <> 10;
在eMP表中查询工资大于部门编号为10的任意一个员工工资的其他部门的员工信息。
ALL运算符
ALL运算符必须与单行操作符结合使用,并且返回行必须匹配所有的子查询的结果。
例: select deptno,ename,sal from emp
where sal > all
(select sal from emp where deptno = 30);
在eMP表中查询公司大于部门编号为30的所有员工工资的员工信息。
关联子查询
单行和多行子查询,内层和外层查询是分开执行的,没有任何关系,外层仅仅是用内层的结果作为一个条件。而关联子查询是指内查询和外查询是相互关联的,内查询的执行需要借助于外查询,而外查询的执行又离不开内查询的执行。
例: select empno,ename,sal from emp a
where sal > (select avg(sal) from emp where job = a.job)
order by job;
在eMP表中使用关联子查询检索工资大于同职位的平均工资的员工信息。
解释:
在上面的查询语句中,内查询使用关联子查询计算每个职位的平均工资,而关联子查询必须知道职位的名称,这个时候,外查询就使用a.job为内存查询提供职位名称,来计算出某个职位的平均工资,如果外查询正在检索的数据行高于平均工资,那么这一行的员工信息会显示出来,否则不显示。
Tips:在执行关联子查询过程中,必须遍历数据表中的每一条记录,因此如果被遍历的数据中有大量的数据记录,则关联子查询的执行速度会比较缓慢
连接(多表联查)
我们在学习或者开发中会设计很多数据表,每个表的信息不是独立存在的,而是存在一定的关系,这样当用户查询某一个表的信息时,很可能需要查询关联数据表的信息,这就是多表关联查询。多表联查要比单表查询复杂的多,在进行多表关联查询时可能会涉及内连接外连接,自然连接,自连接,交叉连接等概念,下面我们对这些内容进行讲解。
多表连接基本查询
使用一张以上的表做查询就是多表查询。
语法: SELECT {DISTINCT} *|列名.. FROM 表名 别名,表名 1 别名
{WHERE 限制条件 ORDER BY 排序字段 ASC|DESC...}
例:查询员工表和部门表。
select * from emp,dept;
我们发现产生的记录数是 56 条,我们还会发现 emp 表是 14 条,dept 表是 4 条,56 正是 emp表和 dept 表的记录数的乘积,我们称其为笛卡尔积。
如果多张表进行一起查询而且每张表的数据很大的话笛卡尔积就会变得非常大,对性能造成影响,想要去掉笛卡尔积我们需要关联查询。在两张表中我们发现有一个共同的字段是 depno,depno 就是两张表的关联的字段,我们可以使用这个字段来做限制条件,两张表的关联查询字段一般是其中一张表的主键,另一张表的外键。
select * from emp,dept where emp.deptno = dept.deptno;
关联之后我们发现数据条数是 14 条,不在是 56 条。
多表查询我们可以为每一张表起一个别名
select * from emp e,dept d where e.deptno = d.deptno;
内连接
内连接是一种常用的多表联查方式,一般使用inner join来实现,其中inner关键字可以省略。内连接简单说就是用join指定连接两个表,用on指定连接的条件。如果进一步限制查询的范围,可以直接在后面添加where子句。
select 字段 from 表1 [inner] join 表2 on 连接条件
例: select e.empno 员工编号, e.ename 员工姓名, d.dname 部门
from emp e join dept d on e.deptno = d.deptno;
在scott的模式下,通过deptno字段来实现连接eMP表和depat表,并检索这两个表中相关字段的信息.
外连接
使用内连接进行查询的时候,返回的结果只包含符合查询条件和连接条件的行,内连接消除了与另一个表中的任何行不匹配的行,而外连接扩展了内连接的结果集,除了返回所有匹配的行之外,还会返回一部分或者全部不匹配的行。
- 左外连接:关键字left outer join 或者 left join
- 右外连接:关键字right outer join或者 right join
- 完全外连接:关键字full outer join 或者full join
左外连接
左外连接的查询结果中,不仅包含了满足连接条件的数据行,还包含了左表中不满足连接条件的数据行。
例: select e.empno,e.ename,e.job,d.deptno,d.dname
from emp e left join dept d
on e.deptno = d.deptno;
EMP表和depat表之间通过deptno列进行左外连接。
我们可以看到图中的null值被记录在结果集中,这说明左外连接的查询结果中,会包含左表中不满足连接条件的数据行。
右外连接
那么对于右外连接也是同样的道理,右外连接的查询结果中不仅包含了满足连接条件的数据行,而且还包含了右表中不满足连接条件的数据行。
例: select e.empno,e.ename,e.job,d.deptno,d.dname
from emp e right join dept d
on e.deptno = d.deptno;
在scott的模式下实现emp表和dept表之间通过deptno列进行右外连接。
从表中我们可以看到,虽然部门编号为40的部门,现在在emp表中还没有员工记录,但是它却出现在查询结果中,这说明右外连接的查询结果会包含右表中不满足连接条件的数据行。
在外连接中,也可以使用外连接的连接运算符“(+) ” 该连接运算符可以放在等号的左边,也可以放在等号的右边,但一定要放在缺少相应相应信息的那一边。
这个+号可以这样来理解: + 表示补充,即哪个表有加号,这个表就是匹配表。所以加号写在右表,左表就是全部显示,故是左连接。
关于使用(+)的一些注意事项:
1.(+)操作符只能出现在where子句中,并且不能与outer join语法同时使用。
2. 当使用(+)操作符执行外连接时,如果在where子句中包含有多个条件,则必须在所有条件中都包含(+)操作符
3.(+)操作符只适用于列,而不能用在表达式上。
4.(+)操作符不能与or和in操作符一起使用。
5.(+)操作符只能用于实现左外连接和右外连接,而不能用于实现完全外连接。
完全外连接
oracle会执行一个完整的左外连接和右外连接查询,然后将查询结果合并,并消除重复的记录行。
例: select e.empno,e.ename,e.job,d.deptno,d.dname
from emp e full join dept d
on e.deptno = d.deptno;
在Scott模式下实现emp表和dept表之间通过deptno列进行完全外连接。
自然连接
自然连接是指第1个表的列和第2个表中具有相同名称的列进行自动连接,这样就不需要用户明确的指定进行连接的列。自然连接使用natural join关键字。但在我们平常开发或者学习中很少用到自然连接,因为它必须具有相同的列名称容,这样在设计表时容易出现未知的错误。
需要注意的是,在使用自然连接时,不能为列指定限定词(即表名或表的别名),否则oracle系统中会出现“ORA-25155:NATURAL连接中的使用的列不能有限定词”的错误提示。
自连接
自连接主要用在自参考表上显示上下级关系或层次关系。自参照表是指在同一张表的不同列之间具有参照关系或主从关系的表。例如emp表包含empno(雇员号)和mgr(管理者号),两者之间就具有参照关系,这样用户就可以通过mgr列与empno列的关系,实现查询某个管理者所管理的下属员工信息。
为了显示雇员及其管理者之间的对应关系,可以使用自连接,因为自连接是在同一张表之间的连接查询,所以必须定义表别名。
例: select e1.ename 下属员工, e2.ename 上层管理者
from emp e2 left join emp e1
on e2.empno = e1.mgr
order by e1.mgr;
在scott模式下,查询所有管理者所管理的下属员工信息。
交叉连接
交叉连接实际上就是不需要任何连接条件的连接,使用cross join 关键字来实现。他的执行结果是一个笛卡尔积,这种查询结果是非常冗余的,但是可以通过where子句来过滤有用的记录信息。
语法: select 列 from 表1 cross join 表2;
多表联查范例
select e.empno,e.ename,
decode(s.grade,1,'一级',2,'二级',3,'三级',4,'四级',5,'五级') grade,
d.dname,e1.empno,e1.ename,
decode(s1.grade,1,'一级',2,'二级',3,'三级',4,'四级',5,'五级') grade
from emp e, emp e1, dept d, salgrade s, salgrade s1
where e.mgr = e1.empno
and e.deptno = d.deptno
and e.sal between s.losal and s.hisal
and e1.sal between s1.losal and s1.hisal
查询出每个员工编号,姓名,部门名称,工资等级和他的上级领导的姓名,工资等级
统计
聚合函数
使用聚合函数可以针对一组数据进行计算,并且得到相应的结果。
- 统计记录数 count()
select count(*) from emp;
查询出所有员工的记录数
注意:这里不建议使用count(*),可以使用一个具体的列以免影响性能,如: select count(ename) from emp;
- 最小值查询 min()
select min(sal) from emp;
查询员工最低工资
- 最大值查询 max()
select max(sal) from emp;
查询员工最高工资
- 查询平均值 avg()
select avg(sal) from emp;
查询员工的平均工资
- 求和函数 sum()
select sum(sal) from emp t where t.deptno = 20;
查询20号部门的员工的工资总和
group by函数
group by 子句经常与聚合函数一起使用,使用group by子句和聚集函数可以实现对查询结果中每一组数据进行分类统计。
常用的函数有avg、count、max、min、sum
例: select job,avg(sal),max(sal),sum(sal),count(job)
from emp
group by job;
在emp表中,使用group by子句对工资记录进行分组,并计算平均工资avg、所有工资的总和sum以及最高工资max和各组的行数。
注意:
-
在使用group by子句时,在select子句的后面,只可以有两类表达式:统计函数和进行分组的列名。
-
在select子句中的列名必须是进行分组的列,除此之外添加的其他列名都是错误的,group by子句后面的列名不可以出现在select词句中。
还不懂的看这儿——>group by详解https://blog.csdn.net/qq_44333320/article/details/106417336 -
在默认情况下,将按照group by子句指定的分组列升序排序,如果需要重新排序,可以使用order by子句指定新的排序顺序。
having子句
having子句通常与group by子句一起使用,在完成对分组结果统计后,可以使用having子句对分组的结果做进一步的筛选。having子句紧跟着groupby子句后面,如果不使用group by子句,having和where其实功能一样,区别就是having子句可以使用avg、sum等聚合函数,而where不可以使用。
tips:记住select语句中子句的处理顺序,在select语句中,首先由from子句找到数据表,where子句则接收from子句输出的数据,而having则接收来自group by、where、from子句的输出。
例: select deptno 部门编号,avg(sal) 平均工资
from emp
group by deptno
having avg(sal) > 2000;
在emp表中,首先通过分组的方式计算出每个部门的平均工资,然后再通过having子句过滤出平均工资大于2000的记录信息。
排序
我们平常在检索数据的时候,如果说数据从数据库里直接读取出来,这时候查询它将按照默认的方式排序,这种排序往往不是我们所需要看到的,尤其是数据比较大的时候,我们看起来会非常的麻烦,所以说我们要对检索的结果进行排序。
语法:
select 字段 from 表 order by [ASC | DESC] [,...n]
order by 关键字ASC表示升序,也是默认排序;DESC表示降序。order by 子句可以根据查询结果中的一个列或者多个列进行排序,并且第一个排序项是主要的排序项,其次是次要的排序项。
例: select deptno,empno,ename from emp order by deptno,empno;
在Scott模式下,检索emp表中所有的数据,并按照部门编号,员工编号排序。
希望对你有所帮助!
转载:https://blog.csdn.net/qq_44333320/article/details/106408361