- 浏览: 157448 次
- 性别:
- 来自: 杭州
-
文章分类
最新评论
-
acetech_sean:
在顶
使用JSTL标签需要的JAR包和JSP页面的引用 -
acetech_sean:
好帖!顶起!!!
使用JSTL标签需要的JAR包和JSP页面的引用 -
acetech_sean:
看帖顶帖,老规矩
使用JSTL标签需要的JAR包和JSP页面的引用 -
akilis:
多谢分享 转走了
jstl和struts2标签截取字符串 -
njl_041x:
学习中。。。
SQL2005 时间戳转换成正常时间 日期
oracle 多表联合查询,统计查询,组函数,order by,having,子查询,集合运算,
关键字: oracle 多表 联合 查询 统计 组函数 order by having 子查询 集合 运算
多表联合查询
通过连接可以建立多表查询,多表查询的数据可以来自多个表,但是表之间必须有适当的连接条件。为了从多张表中查询,必须识别连接多张表的公共列。一般是在WHERE子句中用比较运算符指明连接的条件。
忘记说明表的连接条件是常见的一种错误,这时查询将会产生表连接的笛卡尔积(即一个表中的每条记录与另一个表中的每条记录作连接产生的结果)。一般N个表进行连接,需要至少N-1个连接条件,才能够正确连接。两个表连接是最常见的情况,只需要说明一个连接条件。
两个表的连接有四种连接方式:
* 相等连接。
* 不等连接。
* 外连接。
* 自连接。
1.相等连接
通过两个表具有相同意义的列,可以建立相等连接条件。使用相等连接进行两个表的查询时,只有连接列上在两个表中都出现且值相等的行才会出现在查询结果中。
显示雇员的名称和所在的部门的编号和名称。
执行以下查询:
Sql代码
1. SELECT emp.ename,emp.deptno,dept.dname FROM emp,dept
2. WHERE emp.deptno=dept.deptno;
SELECT emp.ename,emp.deptno,dept.dname FROM emp,dept
WHERE emp.deptno=dept.deptno;
执行结果如下:
Sql代码
1. ENAME DEPTNO DNAME
2. ------------- ------------------------ - ----------
3. SMITH 20 RESEARCH
4. ALLEN 30 SALES
ENAME DEPTNO DNAME
------------- ------------------------ - ----------
SMITH 20 RESEARCH
ALLEN 30 SALES
说明:相等连接语句的格式要求是,在FROM从句中依次列出两个表的名称,在表的每个列前需要添加表名,用“.”分隔,表示列属于不同的表。在WHERE条件中要指明进行相等连接的列。
以上训练中,不在两个表中同时出现的列,前面的表名前缀可以省略。所以以上例子可以简化为如下的表示:
SELECT ename,emp.deptno,dname FROM emp,dept
WHERE emp.deptno=dept.deptno;
2.外连接
在以上的例子中,相等连接有一个问题:如果某个雇员的部门还没有填写,即保留为空,那么该雇员在查询中就不会出现;或者某个部门还没有雇员,该部门在查询中也不会出现。
为了解决这个问题可以用外连,即除了显示满足相等连接条件的记录外,还显示那些不满足连接条件的行,不满足连接条件的行将显示在最后。外连操作符为(+),它可以出现在相等连接条件的左侧或右侧。出现在左侧或右侧的含义不同,这里用如下的例子予以说明。
使用外连显示不满足相等条件的记录。
步骤1:显示雇员的名称、工资和所在的部门名称及没有任何雇员的部门。
执行以下查询:
Sql代码
1. SELECT ename,sal,dname FROM emp,dept
2. WHERE emp.deptno(+)=dept.deptno;
SELECT ename,sal,dname FROM emp,dept
WHERE emp.deptno(+)=dept.deptno;
执行结果为:
Sql代码
1. ENAME SAL DNAME
2. ------------------- -------------- ------------------------
3. CLARK 2450 ACCOUNTING
4. KING 5000 ACCOUNTING
5. MILLER 1300 ACCOUNTING
6. ...
7. TURNER 1500 SALES
8. WARD 1250 SALES
9. OPERATIONS
ENAME SAL DNAME
------------------- -------------- ------------------------
CLARK 2450 ACCOUNTING
KING 5000 ACCOUNTING
MILLER 1300 ACCOUNTING
...
TURNER 1500 SALES
WARD 1250 SALES
OPERATIONS
3.不等连接
还可以进行不等的连接。以下是一个训练实例,其中用到的salgrade表的结构如下:
DESC salgrade
Sql代码
1. 名称 是否为空 类型
2. ------------------------------------------- ------------------ ------------------
3. GRADE NUMBER
4. LOSAL NUMBER
5. HISAL NUMBER
名称 是否为空 类型
------------------------------------------- ------------------ ------------------
GRADE NUMBER
LOSAL NUMBER
HISAL NUMBER
Grade 表示工资等级,losal和hisal分别表示某等级工资的下限和上限。
表的内容为:
Sql代码
1. SELECT * FROM salgrade;
SELECT * FROM salgrade;
Sql代码
1. GRADE LOSAL HISAL
2. ------------------- ------------------- -------------
3. 1 700 1200
4. 2 1201 1400
5. 3 1401 2000
6. 4 2001 3000
7. 5 3001 9999
GRADE LOSAL HISAL
------------------- ------------------- -------------
1 700 1200
2 1201 1400
3 1401 2000
4 2001 3000
5 3001 9999
显示雇员名称,工资和所属工资等级。
执行以下查询:
Sql代码
1. SELECT e.ename, e.sal, s.grade FROM emp e,salgrade s
2. WHERE e.sal BETWEEN s.losal AND s.hisal;
SELECT e.ename, e.sal, s.grade FROM emp e,salgrade s
WHERE e.sal BETWEEN s.losal AND s.hisal;
执行结果为:
Sql代码
1. ENAME SAL GRADE
2. ----------------- -------------------- -------------------
3. JONES 2975 4
4. BLAKE 2850 4
5. CLARK 2450 4
6. SCOTT 3000 4
7. FORD 3000 4
8. KING 5000 5
ENAME SAL GRADE
----------------- -------------------- -------------------
JONES 2975 4
BLAKE 2850 4
CLARK 2450 4
SCOTT 3000 4
FORD 3000 4
KING 5000 5
说明:通过将雇员工资与不同的工资上下限范围相比较,取得工资的等级,并在查询结果中显示出雇员的工资等级。
4.自连接
最后是一个自连接的训练实例,自连接就是一个表,同本身进行连接。对于自连接可以想像存在两个相同的表(表和表的副本),可以通过不同的别名区别两个相同的表。
显示雇员名称和雇员的经理名称。
执行以下查询:
Sql代码
1. SELECT worker.ename||' 的经理是 '||manager.ename AS 雇员经理
2. FROM emp worker, emp manager
3. WHERE worker.mgr = manager.empno;
SELECT worker.ename||' 的经理是 '||manager.ename AS 雇员经理
FROM emp worker, emp manager
WHERE worker.mgr = manager.empno;
执行结果为:
Sql代码
1. 雇员经理
2. -------------------------------------------
3. SMITH 的经理是 FORD
4. ALLEN 的经理是 BLAKE
5. WARD 的经理是 BLAKE
雇员经理
-------------------------------------------
SMITH 的经理是 FORD
ALLEN 的经理是 BLAKE
WARD 的经理是 BLAKE
说明:为EMP表分别起了两个别名worker和manager,可以想像,第一个表是雇员表,第二个表是经理表,因为经理也是雇员。然后通过 worker表的mgr(经理编号)字段同manager表的empno(雇员编号)字段建立连接,这样就可以显示雇员的经理名称了。
注意:经理编号mgr是雇员编号empno之一,所以经理编号可以同雇员编号建立连接。
统计查询
通常需要对数据进行统计,汇总出数据库的统计信息。比如,我们可能想了解公司的总人数和总工资额,或各个部门的人数和工资额,这个功能可以由统计查询完成。
Oracle提供了一些函数来完成统计工作,这些函数称为组函数,组函数不同于前面介绍和使用的函数(单行函数)。组函数可以对分组的数据进行求和、求平均值等运算。组函数只能应用于SELECT子句、HAVING子句或ORDER BY子句中。组函数也可以称为统计函数。
组函数:
AVG:求平均值
COUNT:求计数值,返回非空行数,*表示返回所有行
MAX:求最大值
MIN:求最小值
SUM:求和
STDDEV:求标准偏差,是根据差的平方根得到的
VARIANCE:求统计方差
分组函数中SUM和AVG只应用于数值型的列,MAX、MIN和COUNT可以应用于字符、数值和日期类型的列。组函数忽略列的空值。
使用GROUP BY 从句可以对数据进行分组。所谓分组,就是按照列的相同内容,将记录划分成组,对组可以应用组函数。
如果不使用分组,将对整个表或满足条件的记录应用组函数。
在组函数中可使用DISTINCT或ALL关键字。ALL表示对所有非NULL值(可重复)进行运算(COUNT除外)。DISTINCT 表示对每一个非NULL值,如果存在重复值,则组函数只运算一次。如果不指明上述关键字,默认为ALL。
求有佣金的雇员人数。
执行以下查询:
Sql代码
1. SELECT COUNT(comm) FROM emp;
SELECT COUNT(comm) FROM emp;
返回结果为:
Sql代码
1. COUNT(COMM)
2. ---------------------
3. 4
COUNT(COMM)
---------------------
4
说明:在本例中,没有返回全部雇员,只返回佣金非空的雇员,只有4个人。
求雇员表中不同职务的个数。
执行以下查询:
Sql代码
1. SELECT COUNT( DISTINCT job) FROM emp;
SELECT COUNT( DISTINCT job) FROM emp;
返回结果为:
Sql代码
1. COUNT(DISTINCT JOB)
2. -------------------------------
3. 5
COUNT(DISTINCT JOB)
-------------------------------
5
说明:该查询返回雇员表中不同职务的个数。如果不加DISTINCT,则返回的是职务非空的雇员个数。
分组统计
通过下面的训练,我们来了解分组的用法。
按职务统计工资总和。
步骤1:执行以下查询:
Sql代码
1. SELECT job,SUM(sal) FROM emp GROUP BY job;
SELECT job,SUM(sal) FROM emp GROUP BY job;
执行结果为:
Sql代码
1. JOB SUM(SAL)
2. ----------------- -------------------
3. ANALYST 6000
4. CLERK 4150
5. MANAGER 8275
6. PRESIDENT 5000
7. SALESMAN 5600
JOB SUM(SAL)
----------------- -------------------
ANALYST 6000
CLERK 4150
MANAGER 8275
PRESIDENT 5000
SALESMAN 5600
说明:分组查询允许在查询列表中包含分组列,对以上实例,因为是按职务job分组的,所以在查询列中可以包含job字段,使统计结果很清楚
职务为ANALYST的雇员的总工资为6000,职务为CLERK的雇员的总工资为4150,依此类推。
注意:在查询列中,不能使用分组列以外的其他列,否则会产生错误信息。
错误写法:SELECT ename,job,SUM(sal) FROM emp GROUP BY job;
多列分组统计
可以按多列进行分组,以下是按两列进行分组的例子。
按部门和职务分组统计工资总和。
执行以下查询:
Sql代码
1. SELECT deptno, job, sum(sal) FROM emp
2. GROUP BY deptno, job;
SELECT deptno, job, sum(sal) FROM emp
GROUP BY deptno, job;
执行结果为:
DEPTNO JOB SUM(SAL)
------------------ --------- -----------------------
10 CLERK 1300
10 MANAGER 2450
10 PRESIDENT 5000
20 ANALYST 6000
20 CLERK 1900
20 MANAGER 2975
30 CLERK 950
30 MANAGER 2850
30 SALESMAN 5600
说明:该查询统计每个部门中每种职务的总工资。
分组统计结果限定
对分组查询的结果进行过滤,要使用HAVING从句。HAVING从句过滤分组后的结果,它只能出现在GROUP BY从句之后,而WHERE从句要出现在GROUP BY从句之前。
统计各部门的最高工资,排除最高工资小于3000的部门。
执行以下查询:
Sql代码
1. SELECT deptno, max(sal) FROM emp
2. GROUP BY deptno
3. HAVING max(sal)>=3000;
SELECT deptno, max(sal) FROM emp
GROUP BY deptno
HAVING max(sal)>=3000;
执行结果为:
Sql代码
1. DEPTNO MAX(SAL)
2. ------------------ ------------------
3. 10 5000
4. 20 3000
DEPTNO MAX(SAL)
------------------ ------------------
10 5000
20 3000
说明:结果中排除了部门30,因部门30的总工资小于3000。
注意:HAVING从句的限定条件中要出现组函数。如果同时使用WHERE条件,则WHERE条件在分组之前执行,HAVING条件在分组后执行。
分组统计结果排序
可以使用ORDER BY从句对统计的结果进行排序,ORDER BY从句要出现在语句的最后。
按职务统计工资总和并排序。
执行以下查询:
Sql代码
1. SELECT job 职务, SUM(sal) 工资总和 FROM emp
2. GROUP BY job
3. ORDER BY SUM(sal);
SELECT job 职务, SUM(sal) 工资总和 FROM emp
GROUP BY job
ORDER BY SUM(sal);
执行结果为:
Sql代码
1. 职务 工资总和
2. ---------------- ------------------
3. CLERK 4150
4. PRESIDENT 5000
5. SALESMAN 5600
6. ANALYST 6000
7. MANAGER 8275
职务 工资总和
---------------- ------------------
CLERK 4150
PRESIDENT 5000
SALESMAN 5600
ANALYST 6000
MANAGER 8275
组函数的嵌套使用
在如下训练中,使用了组函数的嵌套。
求各部门平均工资的最高值。
执行以下查询:
Sql代码
1. SELECT max(avg(sal)) FROM emp GROUP BY deptno;
SELECT max(avg(sal)) FROM emp GROUP BY deptno;
执行结果为:
Sql代码
1. MAX(AVG(SAL))
2. -----------------------
3. 2916.66667
MAX(AVG(SAL))
-----------------------
2916.66667
说明:该查询先统计各部门的平均工资,然后求得其中的最大值。
注意:虽然在查询中有分组列,但在查询字段中不能出现分组列。
子查询
我们可能会提出这样的问题,在雇员中谁的工资最高,或者谁的工资比SCOTT高。通过把一个查询的结果作为另一个查询的一部分,可以实现这样的查询功能。具体的讲:要查询工资高于SCOTT的雇员的名字和工资,必须通过两个步骤来完成,第一步查询雇员SCOTT的工资,第二步查询工资高于SCOTT的雇员。第一个查询可以作为第二个查询的一部分出现在第二个查询的条件中,这就是子查询。出现在其他查询中的查询称为子查询,包含其他查询的查询称为主查询。
子查询一般出现在SELECT语句的WHERE子句中,Oracle也支持在FROM或HAVING子句中出现子查询。子查询比主查询先执行,结果作为主查询的条件,在书写上要用圆括号扩起来,并放在比较运算符的右侧。子查询可以嵌套使用,最里层的查询最先执行。子查询可以在SELECT、 INSERT、UPDATE、DELETE等语句中使用。
子查询按照返回数据的类型可以分为单行子查询、多行子查询和多列子查询。
单行子查询
查询比SCOTT工资高的雇员名字和工资。
执行以下查询:
Sql代码
1. SELECT ename,sal FROM emp
2. WHERE sal>(SELECT sal FROM emp WHERE empno=7788);
SELECT ename,sal FROM emp
WHERE sal>(SELECT sal FROM emp WHERE empno=7788);
执行结果为:
Sql代码
1. ENAME SAL
2. -------------- --------------------
3. KING 5000
ENAME SAL
-------------- --------------------
KING 5000
说明:在该子查询中查询SCOTT的工资时使用的是他的雇员号,这是因为雇员号在表中是惟一的,而雇员的姓名有可能相重。SCOTT的雇员号为7788。
也可以包含两个或多个子查询。
Sql代码
1. 在FROM从句中使用子查询
在FROM从句中使用子查询
在FROM从句中也可以使用子查询,在原理上这与在WHERE条件中使用子查询类似。有的时候我们可能要求从雇员表中按照雇员出现的位置来检索雇员,很容易想到的是使用rownum虚列。比如我们要求显示雇员表中6~9位置上的雇员,可以用以下方法。
查询雇员表中排在第6~9位置上的雇员。
执行以下查询:
Sql代码
1. SELECT ename,sal FROM (SELECT rownum as num,ename,sal FROM emp WHERE rownum<=9 )
2. WHERE num>=6;
SELECT ename,sal FROM (SELECT rownum as num,ename,sal FROM emp WHERE rownum<=9 )
WHERE num>=6;
执行结果为:
Sql代码
1. ENAME SAL
2. -------------- --------------------
3. BLAKE 2850
4. CLARK 2450
5. SCOTT 3000
6. KING 5000
ENAME SAL
-------------- --------------------
BLAKE 2850
CLARK 2450
SCOTT 3000
KING 5000
说明:子查询出现在FROM从句中,检索出行号小于等于9的雇员,并生成num编号列。在主查询中检索行号大于等于6的雇员。
注意:以下用法不会有查询结果
SELECT ename,sal FROM emp
WHERE rownum>=6 AND rownum<=9;
集合运算
多个查询语句的结果可以做集合运算,结果集的字段类型、数量和顺序应该一样。
Oracle共有4个集合操作
UNION:并集,合并两个操作的结果,去掉重复的部分
UNION ALL:并集,合并两个操作的结果,保留重复的部分
MINUS:差集,从前面的操作结果中去掉与后面操作结果相同的部分
INTERSECT:交集,取两个操作结果中相同的部分
使用集合的并运算
查询部门10和部门20的所有职务。
执行以下查询:
Sql代码
1. SELECT job FROM emp WHERE deptno=10
2. UNION
3. SELECT job FROM emp WHERE deptno=20;
SELECT job FROM emp WHERE deptno=10
UNION
SELECT job FROM emp WHERE deptno=20;
执行结果为:
Sql代码
1. JOB
2. ---------
3. ANALYST
4. CLERK
5. MANAGER
6. PRESIDENT
JOB
---------
ANALYST
CLERK
MANAGER
PRESIDENT
说明:部门10的职务有PRESIDENT、MANAGER、CLERK;部门20的职务有MANAGER、CLERK、ANALYST。所以两个部门的所有职务(相同职务只算一个)共有4个:ANALYST、CLERK、MANAGER和PRESIDENT。
将UNION改为UNION ALL的结果为:把两条语句查出来的值全部都显示,不去掉重复值
使用集合的交运算
查询部门10和20中是否有相同的职务和工资。
执行以下查询:
Sql代码
1. SELECT job,sal FROM emp WHERE deptno=10
2. INTERSECT
3. SELECT job,sal FROM emp WHERE deptno=20;
SELECT job,sal FROM emp WHERE deptno=10
INTERSECT
SELECT job,sal FROM emp WHERE deptno=20;
执行结果为:
未选定行
说明:部门10的职务有PRESIDENT、MANAGER、CLERK;部门20的职务有MANAGER、CLERK、ANALYST。所以两个部门的相同职务为:CLERK和MANAGER。但是职务和工资都相同的雇员没有,所以没有结果。
使用集合的差运算
查询只在部门表中出现,但没有在雇员表中出现的部门编号。
执行以下查询:
Sql代码
1. SELECT deptno FROM dept
2. MINUS
3. SELECT deptno FROM emp ;
SELECT deptno FROM dept
MINUS
SELECT deptno FROM emp ;
执行结果为:
Sql代码
1. DEPTNO
2. ------------------
3. 40
DEPTNO
------------------
40
说明:部门表中的部门编号有10、20、30和40。雇员表中的部门编号有10、20和30。差集的结果为40。
关键字: oracle 多表 联合 查询 统计 组函数 order by having 子查询 集合 运算
多表联合查询
通过连接可以建立多表查询,多表查询的数据可以来自多个表,但是表之间必须有适当的连接条件。为了从多张表中查询,必须识别连接多张表的公共列。一般是在WHERE子句中用比较运算符指明连接的条件。
忘记说明表的连接条件是常见的一种错误,这时查询将会产生表连接的笛卡尔积(即一个表中的每条记录与另一个表中的每条记录作连接产生的结果)。一般N个表进行连接,需要至少N-1个连接条件,才能够正确连接。两个表连接是最常见的情况,只需要说明一个连接条件。
两个表的连接有四种连接方式:
* 相等连接。
* 不等连接。
* 外连接。
* 自连接。
1.相等连接
通过两个表具有相同意义的列,可以建立相等连接条件。使用相等连接进行两个表的查询时,只有连接列上在两个表中都出现且值相等的行才会出现在查询结果中。
显示雇员的名称和所在的部门的编号和名称。
执行以下查询:
Sql代码
1. SELECT emp.ename,emp.deptno,dept.dname FROM emp,dept
2. WHERE emp.deptno=dept.deptno;
SELECT emp.ename,emp.deptno,dept.dname FROM emp,dept
WHERE emp.deptno=dept.deptno;
执行结果如下:
Sql代码
1. ENAME DEPTNO DNAME
2. ------------- ------------------------ - ----------
3. SMITH 20 RESEARCH
4. ALLEN 30 SALES
ENAME DEPTNO DNAME
------------- ------------------------ - ----------
SMITH 20 RESEARCH
ALLEN 30 SALES
说明:相等连接语句的格式要求是,在FROM从句中依次列出两个表的名称,在表的每个列前需要添加表名,用“.”分隔,表示列属于不同的表。在WHERE条件中要指明进行相等连接的列。
以上训练中,不在两个表中同时出现的列,前面的表名前缀可以省略。所以以上例子可以简化为如下的表示:
SELECT ename,emp.deptno,dname FROM emp,dept
WHERE emp.deptno=dept.deptno;
2.外连接
在以上的例子中,相等连接有一个问题:如果某个雇员的部门还没有填写,即保留为空,那么该雇员在查询中就不会出现;或者某个部门还没有雇员,该部门在查询中也不会出现。
为了解决这个问题可以用外连,即除了显示满足相等连接条件的记录外,还显示那些不满足连接条件的行,不满足连接条件的行将显示在最后。外连操作符为(+),它可以出现在相等连接条件的左侧或右侧。出现在左侧或右侧的含义不同,这里用如下的例子予以说明。
使用外连显示不满足相等条件的记录。
步骤1:显示雇员的名称、工资和所在的部门名称及没有任何雇员的部门。
执行以下查询:
Sql代码
1. SELECT ename,sal,dname FROM emp,dept
2. WHERE emp.deptno(+)=dept.deptno;
SELECT ename,sal,dname FROM emp,dept
WHERE emp.deptno(+)=dept.deptno;
执行结果为:
Sql代码
1. ENAME SAL DNAME
2. ------------------- -------------- ------------------------
3. CLARK 2450 ACCOUNTING
4. KING 5000 ACCOUNTING
5. MILLER 1300 ACCOUNTING
6. ...
7. TURNER 1500 SALES
8. WARD 1250 SALES
9. OPERATIONS
ENAME SAL DNAME
------------------- -------------- ------------------------
CLARK 2450 ACCOUNTING
KING 5000 ACCOUNTING
MILLER 1300 ACCOUNTING
...
TURNER 1500 SALES
WARD 1250 SALES
OPERATIONS
3.不等连接
还可以进行不等的连接。以下是一个训练实例,其中用到的salgrade表的结构如下:
DESC salgrade
Sql代码
1. 名称 是否为空 类型
2. ------------------------------------------- ------------------ ------------------
3. GRADE NUMBER
4. LOSAL NUMBER
5. HISAL NUMBER
名称 是否为空 类型
------------------------------------------- ------------------ ------------------
GRADE NUMBER
LOSAL NUMBER
HISAL NUMBER
Grade 表示工资等级,losal和hisal分别表示某等级工资的下限和上限。
表的内容为:
Sql代码
1. SELECT * FROM salgrade;
SELECT * FROM salgrade;
Sql代码
1. GRADE LOSAL HISAL
2. ------------------- ------------------- -------------
3. 1 700 1200
4. 2 1201 1400
5. 3 1401 2000
6. 4 2001 3000
7. 5 3001 9999
GRADE LOSAL HISAL
------------------- ------------------- -------------
1 700 1200
2 1201 1400
3 1401 2000
4 2001 3000
5 3001 9999
显示雇员名称,工资和所属工资等级。
执行以下查询:
Sql代码
1. SELECT e.ename, e.sal, s.grade FROM emp e,salgrade s
2. WHERE e.sal BETWEEN s.losal AND s.hisal;
SELECT e.ename, e.sal, s.grade FROM emp e,salgrade s
WHERE e.sal BETWEEN s.losal AND s.hisal;
执行结果为:
Sql代码
1. ENAME SAL GRADE
2. ----------------- -------------------- -------------------
3. JONES 2975 4
4. BLAKE 2850 4
5. CLARK 2450 4
6. SCOTT 3000 4
7. FORD 3000 4
8. KING 5000 5
ENAME SAL GRADE
----------------- -------------------- -------------------
JONES 2975 4
BLAKE 2850 4
CLARK 2450 4
SCOTT 3000 4
FORD 3000 4
KING 5000 5
说明:通过将雇员工资与不同的工资上下限范围相比较,取得工资的等级,并在查询结果中显示出雇员的工资等级。
4.自连接
最后是一个自连接的训练实例,自连接就是一个表,同本身进行连接。对于自连接可以想像存在两个相同的表(表和表的副本),可以通过不同的别名区别两个相同的表。
显示雇员名称和雇员的经理名称。
执行以下查询:
Sql代码
1. SELECT worker.ename||' 的经理是 '||manager.ename AS 雇员经理
2. FROM emp worker, emp manager
3. WHERE worker.mgr = manager.empno;
SELECT worker.ename||' 的经理是 '||manager.ename AS 雇员经理
FROM emp worker, emp manager
WHERE worker.mgr = manager.empno;
执行结果为:
Sql代码
1. 雇员经理
2. -------------------------------------------
3. SMITH 的经理是 FORD
4. ALLEN 的经理是 BLAKE
5. WARD 的经理是 BLAKE
雇员经理
-------------------------------------------
SMITH 的经理是 FORD
ALLEN 的经理是 BLAKE
WARD 的经理是 BLAKE
说明:为EMP表分别起了两个别名worker和manager,可以想像,第一个表是雇员表,第二个表是经理表,因为经理也是雇员。然后通过 worker表的mgr(经理编号)字段同manager表的empno(雇员编号)字段建立连接,这样就可以显示雇员的经理名称了。
注意:经理编号mgr是雇员编号empno之一,所以经理编号可以同雇员编号建立连接。
统计查询
通常需要对数据进行统计,汇总出数据库的统计信息。比如,我们可能想了解公司的总人数和总工资额,或各个部门的人数和工资额,这个功能可以由统计查询完成。
Oracle提供了一些函数来完成统计工作,这些函数称为组函数,组函数不同于前面介绍和使用的函数(单行函数)。组函数可以对分组的数据进行求和、求平均值等运算。组函数只能应用于SELECT子句、HAVING子句或ORDER BY子句中。组函数也可以称为统计函数。
组函数:
AVG:求平均值
COUNT:求计数值,返回非空行数,*表示返回所有行
MAX:求最大值
MIN:求最小值
SUM:求和
STDDEV:求标准偏差,是根据差的平方根得到的
VARIANCE:求统计方差
分组函数中SUM和AVG只应用于数值型的列,MAX、MIN和COUNT可以应用于字符、数值和日期类型的列。组函数忽略列的空值。
使用GROUP BY 从句可以对数据进行分组。所谓分组,就是按照列的相同内容,将记录划分成组,对组可以应用组函数。
如果不使用分组,将对整个表或满足条件的记录应用组函数。
在组函数中可使用DISTINCT或ALL关键字。ALL表示对所有非NULL值(可重复)进行运算(COUNT除外)。DISTINCT 表示对每一个非NULL值,如果存在重复值,则组函数只运算一次。如果不指明上述关键字,默认为ALL。
求有佣金的雇员人数。
执行以下查询:
Sql代码
1. SELECT COUNT(comm) FROM emp;
SELECT COUNT(comm) FROM emp;
返回结果为:
Sql代码
1. COUNT(COMM)
2. ---------------------
3. 4
COUNT(COMM)
---------------------
4
说明:在本例中,没有返回全部雇员,只返回佣金非空的雇员,只有4个人。
求雇员表中不同职务的个数。
执行以下查询:
Sql代码
1. SELECT COUNT( DISTINCT job) FROM emp;
SELECT COUNT( DISTINCT job) FROM emp;
返回结果为:
Sql代码
1. COUNT(DISTINCT JOB)
2. -------------------------------
3. 5
COUNT(DISTINCT JOB)
-------------------------------
5
说明:该查询返回雇员表中不同职务的个数。如果不加DISTINCT,则返回的是职务非空的雇员个数。
分组统计
通过下面的训练,我们来了解分组的用法。
按职务统计工资总和。
步骤1:执行以下查询:
Sql代码
1. SELECT job,SUM(sal) FROM emp GROUP BY job;
SELECT job,SUM(sal) FROM emp GROUP BY job;
执行结果为:
Sql代码
1. JOB SUM(SAL)
2. ----------------- -------------------
3. ANALYST 6000
4. CLERK 4150
5. MANAGER 8275
6. PRESIDENT 5000
7. SALESMAN 5600
JOB SUM(SAL)
----------------- -------------------
ANALYST 6000
CLERK 4150
MANAGER 8275
PRESIDENT 5000
SALESMAN 5600
说明:分组查询允许在查询列表中包含分组列,对以上实例,因为是按职务job分组的,所以在查询列中可以包含job字段,使统计结果很清楚
职务为ANALYST的雇员的总工资为6000,职务为CLERK的雇员的总工资为4150,依此类推。
注意:在查询列中,不能使用分组列以外的其他列,否则会产生错误信息。
错误写法:SELECT ename,job,SUM(sal) FROM emp GROUP BY job;
多列分组统计
可以按多列进行分组,以下是按两列进行分组的例子。
按部门和职务分组统计工资总和。
执行以下查询:
Sql代码
1. SELECT deptno, job, sum(sal) FROM emp
2. GROUP BY deptno, job;
SELECT deptno, job, sum(sal) FROM emp
GROUP BY deptno, job;
执行结果为:
DEPTNO JOB SUM(SAL)
------------------ --------- -----------------------
10 CLERK 1300
10 MANAGER 2450
10 PRESIDENT 5000
20 ANALYST 6000
20 CLERK 1900
20 MANAGER 2975
30 CLERK 950
30 MANAGER 2850
30 SALESMAN 5600
说明:该查询统计每个部门中每种职务的总工资。
分组统计结果限定
对分组查询的结果进行过滤,要使用HAVING从句。HAVING从句过滤分组后的结果,它只能出现在GROUP BY从句之后,而WHERE从句要出现在GROUP BY从句之前。
统计各部门的最高工资,排除最高工资小于3000的部门。
执行以下查询:
Sql代码
1. SELECT deptno, max(sal) FROM emp
2. GROUP BY deptno
3. HAVING max(sal)>=3000;
SELECT deptno, max(sal) FROM emp
GROUP BY deptno
HAVING max(sal)>=3000;
执行结果为:
Sql代码
1. DEPTNO MAX(SAL)
2. ------------------ ------------------
3. 10 5000
4. 20 3000
DEPTNO MAX(SAL)
------------------ ------------------
10 5000
20 3000
说明:结果中排除了部门30,因部门30的总工资小于3000。
注意:HAVING从句的限定条件中要出现组函数。如果同时使用WHERE条件,则WHERE条件在分组之前执行,HAVING条件在分组后执行。
分组统计结果排序
可以使用ORDER BY从句对统计的结果进行排序,ORDER BY从句要出现在语句的最后。
按职务统计工资总和并排序。
执行以下查询:
Sql代码
1. SELECT job 职务, SUM(sal) 工资总和 FROM emp
2. GROUP BY job
3. ORDER BY SUM(sal);
SELECT job 职务, SUM(sal) 工资总和 FROM emp
GROUP BY job
ORDER BY SUM(sal);
执行结果为:
Sql代码
1. 职务 工资总和
2. ---------------- ------------------
3. CLERK 4150
4. PRESIDENT 5000
5. SALESMAN 5600
6. ANALYST 6000
7. MANAGER 8275
职务 工资总和
---------------- ------------------
CLERK 4150
PRESIDENT 5000
SALESMAN 5600
ANALYST 6000
MANAGER 8275
组函数的嵌套使用
在如下训练中,使用了组函数的嵌套。
求各部门平均工资的最高值。
执行以下查询:
Sql代码
1. SELECT max(avg(sal)) FROM emp GROUP BY deptno;
SELECT max(avg(sal)) FROM emp GROUP BY deptno;
执行结果为:
Sql代码
1. MAX(AVG(SAL))
2. -----------------------
3. 2916.66667
MAX(AVG(SAL))
-----------------------
2916.66667
说明:该查询先统计各部门的平均工资,然后求得其中的最大值。
注意:虽然在查询中有分组列,但在查询字段中不能出现分组列。
子查询
我们可能会提出这样的问题,在雇员中谁的工资最高,或者谁的工资比SCOTT高。通过把一个查询的结果作为另一个查询的一部分,可以实现这样的查询功能。具体的讲:要查询工资高于SCOTT的雇员的名字和工资,必须通过两个步骤来完成,第一步查询雇员SCOTT的工资,第二步查询工资高于SCOTT的雇员。第一个查询可以作为第二个查询的一部分出现在第二个查询的条件中,这就是子查询。出现在其他查询中的查询称为子查询,包含其他查询的查询称为主查询。
子查询一般出现在SELECT语句的WHERE子句中,Oracle也支持在FROM或HAVING子句中出现子查询。子查询比主查询先执行,结果作为主查询的条件,在书写上要用圆括号扩起来,并放在比较运算符的右侧。子查询可以嵌套使用,最里层的查询最先执行。子查询可以在SELECT、 INSERT、UPDATE、DELETE等语句中使用。
子查询按照返回数据的类型可以分为单行子查询、多行子查询和多列子查询。
单行子查询
查询比SCOTT工资高的雇员名字和工资。
执行以下查询:
Sql代码
1. SELECT ename,sal FROM emp
2. WHERE sal>(SELECT sal FROM emp WHERE empno=7788);
SELECT ename,sal FROM emp
WHERE sal>(SELECT sal FROM emp WHERE empno=7788);
执行结果为:
Sql代码
1. ENAME SAL
2. -------------- --------------------
3. KING 5000
ENAME SAL
-------------- --------------------
KING 5000
说明:在该子查询中查询SCOTT的工资时使用的是他的雇员号,这是因为雇员号在表中是惟一的,而雇员的姓名有可能相重。SCOTT的雇员号为7788。
也可以包含两个或多个子查询。
Sql代码
1. 在FROM从句中使用子查询
在FROM从句中使用子查询
在FROM从句中也可以使用子查询,在原理上这与在WHERE条件中使用子查询类似。有的时候我们可能要求从雇员表中按照雇员出现的位置来检索雇员,很容易想到的是使用rownum虚列。比如我们要求显示雇员表中6~9位置上的雇员,可以用以下方法。
查询雇员表中排在第6~9位置上的雇员。
执行以下查询:
Sql代码
1. SELECT ename,sal FROM (SELECT rownum as num,ename,sal FROM emp WHERE rownum<=9 )
2. WHERE num>=6;
SELECT ename,sal FROM (SELECT rownum as num,ename,sal FROM emp WHERE rownum<=9 )
WHERE num>=6;
执行结果为:
Sql代码
1. ENAME SAL
2. -------------- --------------------
3. BLAKE 2850
4. CLARK 2450
5. SCOTT 3000
6. KING 5000
ENAME SAL
-------------- --------------------
BLAKE 2850
CLARK 2450
SCOTT 3000
KING 5000
说明:子查询出现在FROM从句中,检索出行号小于等于9的雇员,并生成num编号列。在主查询中检索行号大于等于6的雇员。
注意:以下用法不会有查询结果
SELECT ename,sal FROM emp
WHERE rownum>=6 AND rownum<=9;
集合运算
多个查询语句的结果可以做集合运算,结果集的字段类型、数量和顺序应该一样。
Oracle共有4个集合操作
UNION:并集,合并两个操作的结果,去掉重复的部分
UNION ALL:并集,合并两个操作的结果,保留重复的部分
MINUS:差集,从前面的操作结果中去掉与后面操作结果相同的部分
INTERSECT:交集,取两个操作结果中相同的部分
使用集合的并运算
查询部门10和部门20的所有职务。
执行以下查询:
Sql代码
1. SELECT job FROM emp WHERE deptno=10
2. UNION
3. SELECT job FROM emp WHERE deptno=20;
SELECT job FROM emp WHERE deptno=10
UNION
SELECT job FROM emp WHERE deptno=20;
执行结果为:
Sql代码
1. JOB
2. ---------
3. ANALYST
4. CLERK
5. MANAGER
6. PRESIDENT
JOB
---------
ANALYST
CLERK
MANAGER
PRESIDENT
说明:部门10的职务有PRESIDENT、MANAGER、CLERK;部门20的职务有MANAGER、CLERK、ANALYST。所以两个部门的所有职务(相同职务只算一个)共有4个:ANALYST、CLERK、MANAGER和PRESIDENT。
将UNION改为UNION ALL的结果为:把两条语句查出来的值全部都显示,不去掉重复值
使用集合的交运算
查询部门10和20中是否有相同的职务和工资。
执行以下查询:
Sql代码
1. SELECT job,sal FROM emp WHERE deptno=10
2. INTERSECT
3. SELECT job,sal FROM emp WHERE deptno=20;
SELECT job,sal FROM emp WHERE deptno=10
INTERSECT
SELECT job,sal FROM emp WHERE deptno=20;
执行结果为:
未选定行
说明:部门10的职务有PRESIDENT、MANAGER、CLERK;部门20的职务有MANAGER、CLERK、ANALYST。所以两个部门的相同职务为:CLERK和MANAGER。但是职务和工资都相同的雇员没有,所以没有结果。
使用集合的差运算
查询只在部门表中出现,但没有在雇员表中出现的部门编号。
执行以下查询:
Sql代码
1. SELECT deptno FROM dept
2. MINUS
3. SELECT deptno FROM emp ;
SELECT deptno FROM dept
MINUS
SELECT deptno FROM emp ;
执行结果为:
Sql代码
1. DEPTNO
2. ------------------
3. 40
DEPTNO
------------------
40
说明:部门表中的部门编号有10、20、30和40。雇员表中的部门编号有10、20和30。差集的结果为40。
相关推荐
除了基本的SELECT、FROM、WHERE子句,Oracle还支持子查询、连接查询、集合操作(如UNION、INTERSECT、EXCEPT)以及WITH子句(公共表表达式)来构建复杂的查询结构。 总的来说,Oracle的函数和查询机制提供了丰富的...
以上只是Oracle函数和查询的一部分,实际应用中还有更多高级特性和复杂操作,如游标、存储过程、触发器、包、并行查询等,都需要根据具体需求进行深入学习和掌握。Oracle数据库的强大功能和灵活性使得它成为企业级...
4. 多列子查询指的是子查询返回的结果集包含多列数据。 十二、关联子查询 1. 关联子查询依赖于外部查询返回的结果集,往往以主查询返回的每一行作为条件执行一次。 2. 关联子查询的执行过程比非关联子查询更复杂。 ...
7. **集合运算**:集合运算包括UNION(合并结果集)、INTERSECT(交集)和EXCEPT(差集),它们允许从多个查询结果中组合或筛选数据。 8. **创建和管理表**:这涉及CREATE TABLE语句来定义新表,ALTER TABLE用于...
- 子查询的使用:在SELECT、FROM、WHERE和HAVING子句中嵌套查询。 - 非关联子查询和关联子查询:理解这两种子查询的区别和使用场景。 - IN、NOT IN、ANY、ALL子查询:掌握这些操作符在子查询中的应用。 7. **第...
熟练掌握单行函数和组函数,能够极大地提高数据查询、处理和分析的效率,也为数据库的维护和开发工作提供了更多的可能性。通过利用这些函数,开发者能够编写出更为简洁、高效的SQL代码,以应对各种复杂的业务场景。...
本周覆盖了SQL的基础概念、查询语句、函数使用、子句详解以及表的联合和子查询等重要知识点,为后续深入学习Oracle SQL打下了坚实的基础。接下来的一周将继续探索数据操作、表的创建与管理等高级主题,进一步提升SQL...
可以使用WHERE子句进行筛选,ORDER BY子句进行排序,以及GROUP BY和HAVING子句进行分组统计。联接(JOIN)操作则允许从多个表中合并数据。 第五讲:复杂查询 复杂的查询涉及子查询、联接和集合运算。子查询可以在...
#### 表的联合与子查询 - **表的联合**:通过INNER JOIN、LEFT JOIN、RIGHT JOIN和FULL OUTER JOIN实现多表数据的组合。 - **子查询**:嵌套在其他SQL语句中的查询,可用于更复杂的逻辑处理,如EXISTS、ANY和ALL的...
- 子查询和连接查询都可以用来从多个表中获取数据,但是它们的工作方式不同。子查询通常用于过滤条件,而连接查询则是为了组合多个表的数据。 #### 二十、集合并运算 (UNION) - `UNION` 运算符用于合并两个或多个`...
复杂查询是指涉及多个表或者包含子查询的SQL语句。这类查询通常用于解决更复杂的业务问题。 ##### 2.1 子查询 子查询是在一个查询内部嵌套另一个查询的情况。它可以出现在SELECT、WHERE或HAVING子句中。 - **单行子...
- **组函数** 如`COUNT`, `SUM`, `AVG`, `MAX`, `MIN`等用于对一组值进行统计。 8. **GROUP BY和HAVING子句** - **GROUP BY** 用于将数据分组,常与组函数一起使用。 - **HAVING** 用于筛选分组后的数据,与...
- **4.1.2 多行子查询**:返回多个结果的子查询。 - **4.1.3 多列子查询**:返回多列结果的子查询。 - **4.1.4 关联子查询**:子查询与外部查询有关联的行。 - **4.1.5 嵌套子查询**:一个查询中包含另一个查询。 #...
- 多行子查询返回多个值,可以使用IN、ANY/SOME、ALL等操作符与之配合使用。 #### 七、操纵数据 **7.1 学习目的** - 本章主要讲解如何使用数据操纵语言(DML)来进行数据的插入、更新和删除等操作。 **7.2 数据...
组函数用于对一组值进行统计计算,如计数、求和、平均值等。 1. **AVG**:计算平均值。 2. **SUM**:计算总和。 3. **MAX**:找出最大值。 4. **MIN**:找出最小值。 5. **COUNT**:计算行数。 ##### 5.3 组函数...
- **子查询**:作为另一个查询的一部分,可以在SELECT、WHERE、HAVING等子句中使用,分为单行子查询、多行子查询、多列子查询等。 ### 约束与数据字典 - **约束**:用于限制数据的有效性,如PRIMARY KEY、FOREIGN ...
本篇文章将深入探讨“Oracle函数大全”,助你更好地掌握Oracle数据库中的各种函数。 一、数学函数 Oracle数学函数用于执行基本和高级数学运算。例如: 1. `ABS(x)`: 返回x的绝对值。 2. `SQRT(x)`: 计算x的平方根。...
作者通过总结各自多年的软件开发和教学培训经验,与大家分享了掌握Oracle SQL所独有的丰富功能的技巧所在,内容涵盖SQL执行、联结、集合、分析函数、子句、事务处理等多个方面。读者可以学习到以下几个方面的技巧:...
本章节讲解了如何向表中插入数据,从另一个表复制数据,更新表中数据,使用子查询更新多列,删除表中数据,执行基于另一个表的删除操作,以及使用INSERT ALL、MERGE等语句进行复杂的插入操作。还提到了使用DEFAULT值...