语法:
select *(所有列)/列名1.列名2.,,, from 表名 [where 条件] --对整张表的筛选 [group by 列名1[,列名2,...]] 分组 [having 条件] --对分组之后的筛选 [order by 列名 排序方式[,列名2 排序方式2,...] --排序
null查询:与任何运算符进行计算的时候都是null
(与null判断, 不能使用 = != 一定使用 is null 或者 is not null)
nvl(列名, 转换的值) 如果列中值是null, 返回转换的值, 如果列中的值不是null, 返回列的值
select ename, sal + nvl(comm,0) from emp;
多列合并 使用 || 连接符
select ename||'$'|| (sal + nvl(comm,0)) "月收入" from emp e;
去重 关键字 distinct
所有列的最前面
select distinct job from emp;
in(值的集合)
-- 表示列中的值是集合任何一个都满足 select * from EMP where empno in (7369,7788,7902);
between 小值 and 大值:
-- 大于等于小值, 小于等于大值 select * from EMP where sal between 800 and 3000;
模糊查询
列名 like '表达式'
_一个任意的字符 %: 任意多个任意字符
--查询姓名以S开头的 select * from emp where ename like 'S%'; -- 查询姓名由五个字符组成 select * from emp where ename like '_____';
聚合函数
- COUNT():统计指定列不为NULL的记录行数;
- MAX():计算指定列的最大值,如果指定列是字符串类型,那么使用字符串排序运算; a-z
- MIN():计算指定列的最小值,如果指定列是字符串类型,那么使用字符串排序运算;
- SUM():计算指定列的数值和,如果指定列类型不是数值类型,那么计算结果为0;
- AVG():计算指定列的平均值,如果指定列类型不是数值类型,那么计算结果为0;
分组 group by 列
使用group by 进行分组, select 后面只能接 分组中出现的列, 聚合函数
having
对分组的数据进行筛选
注意: where 与having的区别: 筛选
-- 1) 位置不同, where在group by之前, having 是在group by之后
-- **** 2) where 的条件不能使用聚合函数, 使用表所有的列名 having 可以使用聚合函数, 只能使用group by 出现的列
-- 3) where 对整张表进行筛选, having 对分组之后的数据来筛选
多表查询
表连接分类: 内连接, 左外连接, 右外连接
内连接:
A内连接 B 要求A的一条记录一定在B中有一条数据与它对象, B的一条记录需要A有一条记录对应,这样才显示
没有对应的数据, 排除
写法: 非标准写法:
select * from emp e,dept d where e.deptno = d.deptno;
标准写法:
-- select */列名 from 表1 [inner] join 表2 on 连接的条件 select * from emp e inner join dept d on e.deptno = d.deptno;
表连接: 可以n张表进行连接, 连接的条件 不一定是等值连接
select * from emp e join dept d on e.deptno = d.deptno join salgrade s on e.sal BETWEEN s.losal and s.HISAL;
外连接
左外: join左边的表为主, 把左边的表的数据全部查询出来,
右外: join右边的表为主, 把右边的表的数据全部查询出来,
左外连接
左边表的数据全部显示
先查询出左表(即以左表为主),然后查询右表,右表中满足条件的显示出来,不满足条件的显示NULL。
标准写法: left [outer] join -- 左表: emp 右表: dept select * from emp e left outer join dept d on e.deptno = d.deptno;
右外连接
先查询出右表(即以右表为主),然后查询左表,左表中满足条件的显示出来,不满足条件的显示NULL。
结果一样 --标准写法: right [outer] join select * from emp e right join dept d on e.deptno = d.deptno; --左外 select * from dept d left join emp e on e.deptno = d.deptno;
子查询
一个select语句中包含其他的select语句, 这个查询叫: 子查询
子查询出现的位置:
where后,作为条件的一部分;
from后,作为被查询的一条表;
select后, 作为被查询的一列(很少用)
当子查询出现在where后作为条件时,还可以使用如下关键字: 结合 > < >= =<
any 任意一个 >any
all 所以 >all
比较运算符: > < = != .... 要求后面的结果是一个值 -- all(子查询) 所有 >all --> 大于所有(大于最大值) <all --> 小于所有(小于最小值) -- any(子查询) 任意一个 >any --> 大于任意一个(大于最小值) <any-->小于任意一个(小于最大值)
子查询结果集的形式:
单行单列(用于条件)
单行多列(用于条件)
多行单列(用于条件)
多行多列(用于表)
单行单列:
select * from emp where sal > ( select sal from emp where ename='ALLEN' );
单行多列:
select sal from emp where deptno = 30;
多行单列:
select * from emp where sal > all ( select sal from emp where deptno = 30 ); select sal from emp where deptno = 30; --第二种写法: 大于最大值 select * from emp where sal > ( select max(sal) from emp where deptno = 30 --查询出30部门最大值 );
多行多列:
--查询员工编号为7369的员工名称、员工工资(emp)、部门名称、部门地址(dept) --第一种写法: 表连接 select e.ename,e.sal,d.dname,d.LOC from emp e, dept d where e.deptno = d.deptno and e.empno = 7369; --第二种写法: 使用子查询 -- 注意, 如果子查询作为表来使用, 这个子查询的一定要起别名, -- 不是给子查询起别名, 这个别名是给子查询查询出来的虚拟表起的别名 -- 子查询中查询的列取别名, 子查询作为表来用, 虚拟表, 列使用列别名 select e.ename,e.sal,t.dname,t.LOC from emp e ,(select deptno dno,dname,loc from dept) t where e.deptno = t.dno and e.empno=7369;
使用in的子查询
-- in 前面的小括号的列顺序要与 子查询的select 后的列顺序一致 select * from emp where (job,sal) in (select job,sal from emp where ename='MARTIN') and ename !='MARTIN';
【 相关子查询 】:
子查询的执行必须依赖于主查询, 这个子查询不能独立运行, 先主查询,再把主查询的数据传递子查询
【 非相关子查询 】:
前面写的所有的子查询都是非相关子查询:
--非相关子查询 -- in, exists 这两种写法, 有一个效率差异( 内层数据量, 外层数据量) -- 外层数据量大, in 效率高 -- 内层数据量大, exists效率高 select * from dept where deptno in( select deptno from emp where sal > 3000); --相关子查询: exists(子查询) --exists的相关子查询只关心内层查询是否有返回值;当内层没有返回值时,外层也没有结果.如果内层有返回值,将内层的结果去查询外层数据 select * from dept d where exists( select 1 from emp e where e.deptno = d.deptno and e.sal > 3000 );