您的位置:首页 > 数据库

SQL高级查询

2015-12-21 23:32 531 查看
一、子查询:
♠ 子查询 --- 当我们需要执行某条 SQL语句时,需要某些查询的结果作为依据时,先去执行的这条查询语句就是子查询。除了可以用于 DQL , 还可以用于DML 和 DDL语句中。
例1:SELECT ename, sal FROM emp_rs WHERE sal > (SELECT sal FROM emp_rs WHERE ename = 'CLARK')
例2:在 DDL语句中使用 - 以子查询结果快速创建表
CREATE TABLE myemployee AS SELECT e.empno, e.name, e,sal, d.deptno, d.dname, d.loc FROM emp e, dept d WHERE e.deptno = d.deptno
例3:在 DML语句中使用-删除与 CLARK 相同部门的所有员工
DELETE FROM emp WHERE deptno = (SELECT deptno FROM emp WHERE ename = 'CLARK')

♠ 子查询根据查询的结果不同应用也不完全一样。
通常按照查询结果分为:
单行单列子查询:查询结果为 1 个值
多行单列子查询:查询结果为 1 个字段,但是有多条记录
多行多列子查询:看起来结果集像一张表,也常当作表来使用

♠ 子查询在 WHERE 子句中:如果子查询返回多行,主查询中要使用多行比较操作符。
(1) 在子查询中需要引用到主查询的字段数据,使用 EXISTS 关键字
(2) EXISTS 后边的子查询至少返回一行数据,则整个条件返回 true
EXISTS 关键字 --- 其后要跟一个查询语句,只要该查询能查询出至少一条数据, EXISTS 表达式就返回真
例如:查看有员工的部门信息
SELECT deptno, dname FROM dept_rs d WHERE EXISTS (SELECT * FROM emp_rs e WHERE d.deptno = e.deptno)

♠ 子查询在 HAVING 子句中:
例如:查看部门的最低薪水,前提是该部门最低的薪水要高于 30 号部门的最低薪水
SELECT MIN(sal) FROM emp_rs GROUP BY deptno HAVING MIN(sal) >(SELECT MIN(sal) FROM emp_rs WHERE deptno = '30')

♠ 子查询在FROM 子句中:
例如:查看工资高于本部门平均工资的员工信息
SELECT e.ename,e.sal,e.deptno FROM emp_rs e,(SELECT AVG(sal) avg_sal,deptno FROM emp_rs GROUP BY deptno) s WHERE e.deptno = s.deptno AND e.sal > s.avg_sal

二、分页查询:
♥ 定义:当表中数据量很大时,查询表中数据一次性全部查询出来,会导致数据全部加载到内存中,对系统资源占用有很大影响,响应速度也慢,但往往用户也不需要一次性将这么多数据全部查看,这时我们可以分批查询表中数据。由于标准 SQL 中没有对分页进行语法定义,所以不同的数据库中分页的语法不一致。

♥ ROWNUM --- 伪列
(1)该字段并不存在于任何一张表中,但是可以从任何一张表中去查询该字段,当查询该字段时, ORACLE 只要可以从表中查询出一条记录,就会为该条记录中该字段添加“行号”。行号从 1 开始,会自动增长。
例1:SELECT ROWNUM ,ename,sal,job FROM emp_rs

(2)由于 ROWNUM 只有查询出一条记录后,才会为该记录编号,然后 ROWNUM 自增,所以我们不能在第一次查询表中数据时使用 ROWNUM>1 以上的数字进行过滤,否则将得不到任何数据。为此,需要进行两次查询,第一次仅使用 ROWNUM 为结果集编号,在基于这个结果集进行二次查询,根据 ROWNUM 的编号取需要的范围内的记录。
例2:SELECT * FROM (SELECT ROWNUM rn,ename,sal,job,deptno FROM emp_rs) WHERE rn >= 5 AND rn <= 10

(3)错例:SELECT * FROM (SELECT ROWNUM rn,ename,sal,job,deptno FROM emp_rs ORDER BY sal DESC) WHERE rn >= 5 AND rn <= 10
错误原因在于:使用 ROWNUM 对结果集编号是在查询过程中进行的,而 ORDER BY 排序是在查询出结果后进行的,所以,当排序过后,原本的编号顺序就打乱了。为此,我们需要先排序,在将排序后的结果集进行编号,然后取范围才能得到正确的结果。

♥ PageSize :每页显示的条目数
Page : 页数
Start = (page - 1) * pageSize + 1; End = page *pageSize

♥ DECODE 函数
语法: DECODE (expr, search1, result1[,search2, result2…][,default]) 跟 Java中 case 相似
(1)DECODE 用于比较参数 expr的值,如果匹配到哪一个 search 条件,就返回对应的 result结果。
(2)可以有多组 search 和result 的对应关系,如果任何一个 search 条件都没有匹配到,则返回最后 default 的值。
(3)default 参数是可选的,如果没有提供 default 参数值,当没有匹配到时,将返回 NULL 。
例如:SELECT ename,job,sal, DECODE(job,'MANAGER',sal*1.2,'ANALYST',sal*1.1,'SALESMAN',sal*1.05,sal) bonus FROM emp_rs

♥ CASE 语句 --- 与DECODE 函数功能相似,类似于 if…else 的操作
例如:SELECT ename,job,sal CASE job WHEN 'MANAGER' THEN sal*1.2
WHEN 'ANALYST' THEN sal*1.1
WHEN 'SALESMAN' THEN sal*1.05
ELSE sal END
bonus FROM emp_rs
例如:按字段内容分组
SELECT COUNT(*),DECODE(job,'ANALYST','VIP','MANAGER','VIP','OTHER') FROM emp_rs
GROUP BY DECODE(job,'ANALYST','VIP','MANAGER','VIP','OTHER')

三、排序函数:
♦ 作用:可以根据指定的字段分组,再根据另一个指定的字段排序,然后生成一个组内的编号。

♦ ROW_NUMBER()
语法: ROW_NUMBER() OVER(PARTITION BY col1 ORDER BY col2)
(1) 表示根据col1 分组,在分组内部根据 col2 排序;
(2)此函数计算的值就表示每组内部排序后的顺序编号,组内连续且唯一。
例如:查看每个部门的工资排名情况
SELECT ename,sal,deptno,ROW_NUMBER() OVER(PARTITION BY deptno ORDER BY sal DESC) rank FROM emp_rs

♦ RANK() --- 生成不连续也不唯一的数字
语法: RANK () OVER(PARTITION BY col1 ORDER BY col2)
(1)表示根据col1 分组,在分组内部根据 col2 给予等级标识;
(2)等级标识即排名,相同的数据返回相同排名;
(3)跳跃排序,如果有相同数据,则排名相同,比如并列第二,则两行数据都标记为 2 ,但下一位将是第四名。
(4)RANK() 有重复值,而 ROW_NUMBER没有重复值。
例如:查看每个部门的工资排名情况
SELECT ename,sal,deptno, RANK() OVER(PARTITION BY deptno ORDER BY sal DESC) rank FROM emp_rs

♦ DENSE_RANK --- 生成连续但不唯一的数字
语法: DENSE_RANK () OVER(PARTITION BY col1 ORDER BY col2)
(1)表示根据col1 分组,在分组内部根据 col2 给予等级标识;
(2)等级标识即排名,相同的数据返回相同排名;
(3)连续排序,如果有并列第二,下一排序将是三。
例如:查看每个部门的工资排名情况
SELECT ename,sal,deptno, DENSE_RANK () OVER(PARTITION BY deptno ORDER BY sal DESC) rank FROM emp_rs

四、集合操作:
♣ 定义:对查询的结果集进行操作。

♣ UNION 、UNION ALL
(1)用来获取两个或两个以上结果集的并集
(2)UNION 操作符会自动去掉合并后的重复记录
(3)UNION ALL 返回两个结果集中的所有行,包括重复的行
(4)UNION 操作符对查询结果排序, UNION ALL 不排序
例如:合并职位是 ’MANAGER’ 的员工和薪水大于 2500的员工集合
SELECT ename, job, sal FROM emp_rs WHERE job = 'MANAGER' UNION SELECT ename, job, sal FROM emp_rs WHERE sal > 2500
SELECT ename, job, sal FROM emp_rs WHERE job = 'MANAGER' UNION ALL SELECT ename, job, sal FROM emp_rs WHERE sal > 2500

♣ INTERSECT
(1)获得两个结果集的交集,只用同时存在于两个结果集中的数据,才被显示输出。
(2)使用INTERSECT 操作符后的结果集会以第一列的数据作升序排列
例如:显示职位是 ’MANAGER’ 的员工和薪水大于 2500的员工的交集
SELECT ename, job, sal FROM emp_rs WHERE job = 'MANAGER' INTERSECT SELECT ename, job, sal FROM emp_rs WHERE sal > 2500

♣ MINUS
(1)获取两个结果集的差集。
(2)只有在第一个结果集中存在,在第二个结果集中不存在的数据,才能被显示出来,也就是结果集一减去结果集二的结果
例如:列出职位是 MANAGER 但薪水低于2500 的员工记录
SELECT ename, job, sal FROM emp_rs WHERE job = 'MANAGER' MINUS SELECT ename, job, sal FROM emp_rs WHERE sal > 2500

五、高级分组函数:
♜ ROLLUP 函数
定义:GROUP BY 子句的扩展,可以生产与使用 UNION ALL 来组合单个分组查询时相同的结果集,用来简化和高效的实现统计查询。
语法:GROUP BY ROLLUP(x1,x2,x3,...) 。
比如写为GROUP BY ROLLUP(a,b,c),那么分组有 4 种分组,分别按照:
GROUP BY a,b,c
GROUP BY a,b
GROUP BY a
全表看做一组统计一次,然后再将上述的四种分组结果并在一个结果集中显示。
例如:全年销售额
SELECT year_id,month_id,day_id,SUM(sales_value) FROM sales_tab_rs GROUP BY ROLLUP(year_id,month_id,day_id) ORDER BY year_id,month_id,day_id

♜ CUBE 函数
定义:将指定的参数字段的每种组合都进行一次分组,然后将这些组合统计的结果集并在一起显示,分组次数是“ 2 的参数个数次方“。
语法:CUBE(x1,x2,x3,...)
比如写为CUBE(a,b,c) ,三个参数就是 2的三次方 8 种。
例如: SELECT year_id,month_id,day_id,SUM(sales_value) FROM sales_tab_rs GROUP BY CUBE(year_id,month_id,day_id) ORDER BY year_id,month_id,day_id

♜ GROUPING SETS 函数
定义:可以根据自定义的组合方式进行分组,然后将这些分组的结果并在一个结果集中显示。
语法:GROUPING SETS(a,b,…)
例如:查看每天与每月的销售额
SELECT year_id,month_id,day_id,SUM(sales_value) FROM sales_tab_rs GROUP BY GROUPING SETS((year_id,month_id,day_id),(year_id,month_id)) ORDER BY year_id,month_id,day_id
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: