思维导图
一.基础语法
1.查询所有列或者特定列
--查询订单产品,产品品名资料
SELECT oeb04,oeb06 FROM oeb_file;
2.消除重复行
--查询订单产品,产品品名资料,且结果消除重复行(请对比SQL示例1)
SELECT DISTINCT oeb04,oeb06 FROM oeb_file;
3.使用算术表达式(+,-,*,/)以及别名
--as指定列别名(列别名也可以不使用as,直接在查询列后面指定即可)
--SQL中使用乘法运算*
SELECT oeb01 as "订单单号", oeb04 as "订单产品",
oeb06 as "产品品名",oeb12*oeb13 as "订单金额"
FROM oeb_file
4.使用nvl函数处理算术表达式运算栏中的空值问题
如果查询的栏位参与+ - / *算术运算,只要参与运算的栏位有一个为空值,则会导致整个运算结果为空值。
nvl(expr1,expr2)如果expr1不为空,则返回expr1,否则返回expr2;expr1与expr2可以是任意数据类型,但是expr1与expr2需是相同的数据类型
nvl2(expr1,expr2,expr3)如果expr1不为空,则返回expr2,否则返回expr3;expr1可以是任意数据类型,但是expr2与expr3需是相同的数据类型
-- 用nvl函数处理空值问题 ,ta-oeb013 为本司客制栏位冲销数量,值为空
SELECT oeb01 as "订单单号", oeb04 as "订单产品",
oeb06 as "品名",oeb12-oeb24-nvl(ta_oeb013,0) as "订单未交量"
FROM oeb_file
-- 用nvl2函数处理空值问题 ,ta-oeb013 为本司客制栏位冲销数量,值为空
SELECT oeb01 as "订单单号", oeb04 as "订单产品",oeb06 as "品名",
nvl2(ta_oeb013,oeb12-oeb24-ta_oeb013,oeb12-oeb24) as "订单未交量"
FROM oeb_file
5.where条件子句
常用的WHERE条件如下:
- 比较操作符: 等于:=,不等于:<>,!=,大于:> , 大于或等于:>= ,小于或等于:<=,小于:<
- 匹配于列表值:IN( ) ,EXISTS()
- 在两值之间:BETWEEN .. AND ..
- 测试是否为NULL:IS NULL (注意:"没有空格"、"一个或多个空格" 与 IS NULL 是不同的)
- 匹配于字符样式:LIKE,执行模糊查询需要使用LIKE,常用LIKE通配符如下:
%:匹配0个或多个字符
_ :匹配单个字符
注意:如果模糊查询本身要查的栏位资料里面包含有'%'或'_'字符时,则需要使用转义字符ESCAPE
如果某值是空则并不能用LIKE "%"匹配的到,写SQL查异常这点经常出错
- 常用的WHERE条件逻辑操作符:逻辑与:AND,逻辑或:OR,取反:NOT
--查询Tiptop GP用户账号中带有'_'下划线的用户信息,escape用'a'做转义字符且2011/03月期间开通的账号
SELECT * FROM zx_file
WHERE zx03 = '2G69'
AND zx01 LIKE '%a_%' ESCAPE 'a'
AND zxdate BETWEEN to_date('2011/03/01','YYYY/MM/DD') AND DFSto_date('2011/03/31','YYYY/MM/DD')
6.分组 GROUP BY
Oracle数据分组通过使用GROUP BY子句指定要分组的列
使用分组函数如COUNT、AVG、SUM、MAX、MIN等显示统计结果
使用HAVING子句限制分组显示结果(注意:having后面必须接分组函数)
- 如果查询有分组函数计算,则先将WHERE条件符合的资料计算,HAVING子句只是显示分组显示的结果,不参与分组函数的 计算
- 常用分组函数:
COUNT:取得行数
MAX:取得列或运算式的最大值,适用于任何数据类型 MIN:取得列或运算式的最小值,适用于任何数据类型
AVG:取得列或运算式的平均值,适用于任何数据类型 SUM:取得列或运算式的总和,只适用于数字类型
VARIANCE:取得列或运算式的方差,只适用于数字类型 STDDEV:取得列或运算式的偏差,只适用于数字类型
- 分组函数 只能够 出现在选择列表、ORDER BY、HAVING子句中,不能出现在 WHERE和GROUP BY子句中
- 除了COUNT(*)之外,其他分组函数都会忽略NULL行
- 执行SELECT语句时,选择列必须出现在GROUP BY子句中
--查询所有部门不同年月中的部门最低、平均、最高薪资,且部门当年月份领薪人员数>=3个
SELECT cqk05,cqk03,cqk031,MIN(cqk30),AVG(cqk30),MAX(cqk30)
FROM cqk_file
GROUP BY cqk05,cqk03,cqk031 --多列分組
HAVING COUNT(distinct cqk09)>=3
ORDER BY 1 DESC,2 ASC,3 ASC
- 使用roll up 进行统计的小计,会为每个分组返回小计记录,均资再平均,最低再求最低,最高再求最高
--统计2G80部门各人员所有年月内的均资、最低薪资、最高薪资
--rollup 均资再平均,最低再求最低,最高再求最高
SELECT cqk09,AVG(cqk30),MIN(cqk30),MAX(cqk30) FROM cqk_file
WHERE cqk05 = '2G80'
GROUP BY ROLLUP (cqk09)
- 当roll up后有两个参数时,会统计deptno,job相同的小计,再统计deptno相同的小计,再统计所有的小计
select deptno,job,sum(sal) from emp
group by rollup(deptno,job) order by deptno;
7.ORDER BY desc (升序排序:默认),ORDER BY asc (降序排序) 将查询出来的资料排序
- 排序时也可以指定多列排序、非选择资料栏位排序、别名排序、列位置编号排序
SELECT zx01,zx02 as "姓名",zx03,zx04 FROM zx_file
WHERE zx03 = '2G69' or zx03 = '2G60'
ORDER BY zx01 asc,"姓名",zx03 asc,zx04 desc --不同列排序必须分别指定排序规则
- 二.连接查询
- 查询的资料列如果在FROM子句后面所列的表或视图有多个,则必须在查询的资料栏位前面加上表或视图名作为首码,否则会引起错误
- 当使用连接查询时必须在WHERE子句中指定连接的条件,否则会产生笛卡尔积(X*Y)
- 使用别名可以简化SQL的编写,别名必须跟在表或视图的后面
2.1简单连接查询
----查询tiptop GP系统用户帐号和部门信息
SELECT zx_file.zx01,zx_file.zx02,zx_file.zx03,gem_file.gem02
FROM zx_file,gem_file
WHERE zx_file.zx03 = gem_file.gem01
----等同于查询tiptop GP系统用户帐号和部门信息
SELECT zx01,zx02,zx03,gem02
FROM zx_file,gem_file
WHERE zx03 = gem01
2.2内连接
- 内连接INNER JOIN:用于返回满足条件的所有记录,默认情况下在执行查询如果没有指定任何连接操作,则此查询SQL即为内连接
--查询tiptop系统用戶信息
--或使用inner join
SELECT zx01 as "用户ID",zx02 as "用户姓名",zx03 as "部门ID",gem02 as "部门简称"
FROM zx_file JOIN gem_file ON zx03 = gem01
2.3左外连接
- 左外连接LEFT JOIN/LEFT OUTER JOIN:不仅返回满足连接条件的结果集而且返回不满足连接条件的但是位于连接操作符左边 表或视图的结果集
--或 left outer join
SELECT zx01,zx02,zx03,gem02 FROM zx_file
LEFT JOIN gem_file ON zx03 = gem01
--等同于如下使用+操作符的SQL语句
--使用+操作符进行左外连接 等同 left join .. on .. 注意+的位置
SELECT zx01,zx02,zx03,gem02
FROM zx_file,gem_file
WHERE zx03 = gem01(+)
2.4右外连接
- 右外连接RIGHT JOIN/RIGHT OUTER JOIN:不仅返回满足连接条件的结果集而且返回不满足连接条件的但是位于连接操 作符右边 表或视图的结果集
--或 right outer join
SELECT zx01,zx02,zx03,gem02 FROM zx_file
RIGHT JOIN gem_file on zx03 = gem01
--等同于如下使用 + 操作符的SQL语句
--使用+操作符进行右外连接 等同 right join .. on .. 注意+的位置
SELECT zx01,zx02,zx03,gem02
FROM zx_file,gem_file
WHERE zx03(+) = gem01
2.5完全外连接
- 完全外连接FULL JOIN/FULL OUTER JOIN:不仅返回满足连接条件的结果集而且返回不满足连接条件的位于连接操作符 左右边表或视图的结果集
--或 full outer join
SELECT zx01,zx02,zx03,gem02 FROM zx_file
FULL JOIN gem_file ON zx03 = gem01
2.6自连接
- 自连接查询:同一张表之间的连接查询,主要用在自参照表上显示同一张表不同栏位列的关系
select a.id,a.name,a.score as "语文",b.score as "数学",c.score as "英语"
from test026 a,test026 b,test026 c
where a.id=b.id and a.subject='语文' and b.subject='数学'
and a.id=c.id and c.subject='英语';
三.子查询
- 也称嵌套查询,是指嵌入在其他SQL语句中的SELECT语句
- 应用: 通过在WHERE、HAVING、START WITH子句中使用子查询可以提供条件值
- 通过在UPDATE语句中使用子查询可以修改一列或多列数据
- 通过在INSERT或CREATE TABLE语句中使用子查询可以将来源表数据插入到目标表中
- 通过在CREATE VIEW或是CREATE MATERIALIZED VIEW中使用子查询可以定义视图
- 注意:当在DDL语句中引用子查询时可以带有ORDER BY子句,但是当在WHERE子句、SET子句中引用子查询时则不可以 带有ORDER BY子句
3.1单行子查询:只返回一行数据的子查询
--查询部门简称为"ERP"的所有账号信息
SELECT zx01,zx02,zx03 FROM zx_file
WHERE zx03 = (SELECT gem01 FROM gem_file WHERE gem02 = 'ERP')
3.2多行子查询:只返回多行数据的子查询
- 当在WHERE子句中使用多行子查询时,必须使用多行比较符IN、ALL、ANY
IN:匹配子查询结果中的任意一个值即可
--查询部门别存在部门信息gem_file中且部门编号是2G开头的人员账号信息
SELECT zx01,zx02,zx03 FROM zx_file
WHERE zx03 IN (SELECT gem01 FROM gem_file WHERE gem01 LIKE '2G%');
ALL:必须要符合子查询结果中的所有值, 不能单独使用,需配合单行比较符(=,>,<.>=,<=,<>,!=)使用
--查询内销订单中接单金额>所有外销订单金额的订单明细
SELECT oea01 as "订单",oeb04 as "产品",oeb12*oeb13 as "金额"
FROM oeb_file,oea_file
WHERE oea01= oeb01
AND oea08 = '1'
AND (oeb12*oeb13 > ALL (
SELECT oeb12*oeb13 FROM oeb_file
WHERE oea01 = oeb01 AND oea08 = '2'
)
)
ANY:只要符号子查询结果中的任意值即可,不能单独使用,需配合单行比较符(=,>,<.>=,<=,<>,!=)使用
--查询接单金额等于任意一个以ZE1-1106开头的订单的接单金额的订单明细
SELECT oeb01 as "订单",oeb04 as "产品",oeb12*oeb13 as "金额"
FROM oeb_file
WHERE oeb12*oeb13 = ANY(
SELECT oeb12*oeb13
FROM oeb_file
WHERE oeb01 like 'ZE1-1108%'
)
3.3多列子查询
--列的顺序一定要相同
select * from emp
where (deptno,job)=(select deptno,job from emp where ename='SMITH')
--查询未转工单的订单+项次
SELECT oeb01 as "未转工单订单",oeb03 as "订单项次",oeb04 as "产品",oeb06 as "品名"
FROM oeb_file
WHERE (oeb01,oeb03) NOT IN (select sfb22,sfb221 FROM sfb_file)
3.4内嵌视图
在FROM子句中使用子查询:FROM子句中使用的子查询,该子查询会被当做视图看待,也称内嵌视图
--查询2013年3月 薪资高于或等于本部薪资平均水平的人员
SELECT cqk_file.cqk05 as "部门编号",cqk09 as "员工姓名",
cqk30 as "薪资",avgsalary as "部门均资"
FROM cqk_file,(SELECT cqk05,avg(cqk30) avgsalary FROM cqk_file
WHERE cqk03 = 2012 and cqk031 = 3
GROUP BY cqk05
) avg_salary
WHERE cqk_file.cqk05 = avg_salary.cqk05
AND cqk_file.cqk30 >= avg_salary.avgsalary
AND cqk03 = 2013 AND cqk031 = 3
3.5相关子查询
- 相关子查询是指需要应用主查询列表中的子查询语句,需要通过谓词EXISTS来实现
- 当使用EXSISTS谓词时,如果子查询存在返回结果则条件返回TRUE,否则返回FALSE
--查询部门存在于部门别gem_file中且部门编号为2G69的tiptop系统用户
--使用EXISTS,因为gem_file有2G69部门资讯,所以子查询返回的条件为true
SELECT zx01,zx02,zx03 FROM zx_file
WHERE EXISTS (
SELECT 1 FROM gem_file
WHERE zx_file.zx03 = gem_file.gem01 AND gem01 = '2G69'
)
四.合并查询
- 语法:SELECT 语句1 [UNION |UNION ALL |INTERSECT | MINUS] SELECT 语句2
- 这些集合操作符具有相同的优先级,当同时使用多个操作符时会按照从左到右的方式应用这些集合操作符
- 使用集合操作符时必须确保不同的查询语句查询的列的个数相同且类型也必须匹配
- 子句不能有ORDER、GROUP,必须放在整个语句的末尾
4.1 UNION
获取两个结果的并集,且去掉合并结果中重复的记录
--UNION应用:查询tiptop系统用户名以ta开头和部门编号是2G69的所有用户
SELECT zx01,zx02,zx03 FROM zx_file WHERE zx01 LIKE 'te%'
UNION
SELECT zx01,zx02,zx03 FROM zx_file WHERE zx03 = '2G69'
4.2 UNION ALL
--UNION ALL应用:查询tiptop系统用户名以ta开头和部门编号是2G69的所有用户
SELECT zx01,zx02,zx03 FROM zx_file WHERE zx01 LIKE 'te%'
UNION ALL
SELECT zx01,zx02,zx03 FROM zx_file WHERE zx03 = '2G69'
4.3 INTERSECT
取两个结果的交集
--INTERSECT应用:查询tiptop系统用户名以ta开头且部门编号是2G69的所有用户
SELECT zx01,zx02,zx03 FROM zx_file WHERE zx01 LIKE 'te%'
INTERSECT
SELECT zx01,zx02,zx03 FROM zx_file WHERE zx03 = '2G69'
4.4 MINUS
获取两个结果集的差集,返回在第一个结果集中存在但是第二个结果集中不存在的记录
--MINUS应用:注意查询结果和上述的差别
SELECT zx01,zx02,zx03 FROM zx_file WHERE zx01 LIKE 'te%'
MINUS
SELECT zx01,zx02,zx03 FROM zx_file WHERE zx03 = '2G69'
五.复杂语法
5.1 case关键字
- 简单CASE语句
语法:
--case到end之间相当于一个具体的值,可以做运算,取别名,嵌套case 等等。
--只要把case到end当作一个运算结果的表达式就可以了。
case exp when comexp then returnvalue
...
when comexp then returnvalue
else returnvalue
end
举例:
select cust_last_name,
case credit_limit when 100 then 'low'
when 5000 then 'high'
else 'medium'
end
from customers;
- 搜索CASE语句
语法发杂语法
case when boolean then return value
...
hen boolean then return value
else retur nvalue
end
举例:
select case when id between 1 and 10 then 'low'
when id between 20 and 30 then 'mid'
when id between 40 and 50 then 'high'
else 'unknow'
end
from product;
--简单case和搜索case之间的区别:
1. 简单case只能是when后面的表达式完全匹配case后的表达式,相当于 =,所以也不能匹配null。
2. searched case可以作为比较条件,那么可以使用like、!=、between ..and、<、=、is null、is not null等,比简单case的使用更加广泛,完全可以替代简单case。
--注意事项:
1.case 表达式返回的是一个确定的value,若前面的都不匹配,则返回else中的项.
2.简单case 中的表达式,when 后面的表达式类型应该全部保持一致.
3.所有的then 后面的return_value类型要保持一致.
4.对于简单case 表达式,也就是case 表达式 when…那么when null 总是取不到。也就是case 后面的表达式如果值为null,不会与when null 匹配,只会与else匹配.
5.对于searched case来说,有自动类型转换,只要条件成立就可以。
如:select case when 1='1' then 1 end from dual; 其中1='1'条件成立
值得一提的是: sql中的case语句与pl/sql中的case语句的不同之处:
前者的else不是必须的,如果没有匹配就返回null;后者的else不写,则报case_not_found异常.
--case中嵌套子查询
Case语句中可以使用子查询,但是必须返回一行,不可以是多行.
select case (select count(*) as s1 from t1 where a = 1)
when (select count(*) as s2 from t1, t2 where t1.a = t2.a and t2.a =
1)
then '相等'
else '不相等'
end
from dual;
5.2树查询
可以实现类似树结构的查询,语法:
SELECT ... FROM + 表名
WHERE + 条件3
START WITH + 条件1
CONNECT BY PRIOR + 条件2
--示例
Select * From DEMO
Start With ID = '00001'
Connect By Prior ID = PID
- 条件1: 表示从哪个节点开始查找, 也就是通过条件1 查询到的数据, 作为后续查询的起始节点(参数).
当然可以放宽限定条件,如 ID in ('00001', '00011')以取得多个根节点,也就是多棵树;在连接关系中,除了可以使用列明外,还允许使用列表达式。
如果省略Start With
就默认把所有满足查询条件的Tree整个表中的数据从头到尾遍历一次,每一个数据做一次根,然后遍历树中其他节点信息.
- 条件2: 是连接条件,其中用PRIOR表示上一条记录,例如CONNECT BY PRIOR ID = PID,意思就是上一条记录的ID是本条 记录的PID,即本记录的父亲是上一条记录。CONNECT BY子句说明每行数据将是按照层次顺序检索,并规定将表中 的数据连入树形结构的关系中。
Prior 在父节点的一侧表示, 自底向上查, 在 子节点的一侧表示 自上向下查询;
条件3: 不能用在 Connect By 后, 这里的条件判断, 等价于 在最后查询出结果列表之后, 再进行条件筛选; 并非 删除掉 节点及子 节点;
关键字:
- nocycle关键字:有时候数据本身 不合理会导致出现循环的问题, 如 将上述的 ID '00001' 记录的 'PID' 也改为 '00001', 会出现循 环的问题, 这是, 需要用到 nocycle 即可消除循环;
- connect_by_isleaf :表示当前节点是否是叶子节点
- level 表示当前节点所处层级, 这里的层级指的是 从 start with 查询到的节点开始往下算起, 当前属于第几层级
Select ID, PID, DSC,
connect_by_isleaf isLeaf,
LEVEL
From DEMO
Connect By nocycle Prior ID = PID
Start With ID = '00001';
--结果
ID PID DSC isLeaf LEVEL
00001 00001 中国 0 0
00011 00001 陕西 0 1
00111 00011 西安 1 2
00112 00011 咸阳 1 2
00113 00011 延安 1 2
00012 00001 贵州 1 1
00013 00001 河南 1 1
- SIBLINGS关键字:它会保护层次,并且在每个等级中按expre排序。
Select ID, PID, DSC,
connect_by_isleaf,
LEVEL
From DEMO
Start With ID = '00001'
Connect By nocycle Prior ID = PID
ORDER By DSC
--结果, 仅贴出部分数据(层级结构被破坏了)
00012 00001 贵州 1 2
00013 00001 河南 1 2
00011 00001 陕西 0 2
00111 00011 西安 1 3
00112 00011 咸阳 1 3
00113 00011 延安 1 3
00001 -1 中国 0 1
--ORDER SIBLINGS By DSC
Select ID, PID, DSC,
connect_by_isleaf,
LEVEL
From DEMO
Start With ID = '00001'
Connect By nocycle Prior ID = PID
ORDER SIBLINGS By DSC
--结果(Level 层级不变)
00001 -1 中国 0 1
00012 00001 贵州 1 2
00013 00001 河南 1 2
00011 00001 陕西 0 2
00111 00011 西安 1 3
00112 00011 咸阳 1 3
00113 00011 延安 1 3
本文由别人的文章总结而来,纯属抛砖引玉!
基本语法:https://blog.csdn.net/yihuiworld/article/details/44699923
case when:https://blog.csdn.net/skysky01/article/details/53466401/
start with:https://www.cnblogs.com/zyzdisciple/p/7873584.html