文章目录
- 批量生成 SQL 语句/拼接字符串
- 多表关联查询 + where 子句
- 示例(一)
- 示例(二)
- 普通的表间内连接查询语句
- 关键字 distinct 用法说明
- Oracle 数据库的分组排序查询
- Oracle 数据库 cast 函数
- Oracle 数据库 sum 函数的高级用法
- Oracle 数据库多层子查询嵌套查询
- 关联子查询
- 数据库如何把纵向列表转换成横向列表
批量生成 SQL 语句/拼接字符串
select 'update t_pf_menu set a1='''||t.a1||''' where a2='''|| t.a2||''';'
from tesst t;
select 'update t_busop set busname='''||t.busname||''',icon='''||t.icon||''' where busopid='''|| t.busopid||''';'
from lwx t;
SQL 语句解释:
||
是表示两段字符串拼接起来,' '
里面是拼接的字符串, ' '' '
表示字符串里面有个单引号,''
表示一个单引号哦。
t.a1
表示取 t
表的 a1
字段的值,注意变量不要加任何的引号哦。
注意:
Oracle 数据库字符串拼接符号 ||
,而MySQL 数据库的字符串拼接使用函数 concat(str1,str2),str1、str2 是指要拼接的两个字符串
多表关联查询 + where 子句
示例(一)
select s.name,s.age,c.course_name
from student s
left outer join course c
on s.course_id=c.course_id
where c.course_id='0707';
上述查询语句执行过程如下:
- 先打开表 student 和 course
- 接着根据关联条件(s.course_id=c.course_id)将 student 和 course 将两张表进行关联
- 接着将匹配结果生成一张虚表,即将符合条件的两张表的数据合并成一张虚表 v1
- 再根据 where 条件把虚表 v1 中符合
c.course_id='0707'
的记录筛选出来,生成虚表 v2 - 最后执行 select 子句把指定字段的数据获取到,生成虚表 v3,v3 就是最后的查询结果
左外连接 left outer join 执行效果说明:
left outer join 的查询结果是这样的,如果匹配成功的那么两张表的相关字段的数据会提取出来,如果匹配不成功的,则左边的数据提取出来,右边表的相应字段值则为空。
错误理解:
这个 where 子句并不是先对 course 表进行筛选再和 student 表进行关联查询,而是进行关联匹配的同时进行筛选,匹配成功且符合筛选条件的记录才提取出来,如果只是匹配成功但是不符合筛选条件的剔除掉。
示例(二)
select cmcltname,jurperson,special,d.name,ecotype,depcode from $prdline.securiorg s left outer join $platform.t_pf_datadict d on s.tecgrd=d.code where d.ddfld='tecgrd';
执行过程简单说明:
数据库是按照这样的顺序来执行 SQL 语句的,首先 securiorg 和 t_pf_datadict 两张表通过 s.tecgrd=d.code 关联条件进行做左连接,这样就得到连接后的结果集,再执行 where 语句进行筛选,再执行 select 语句得到最后想要的结果集。
普通的表间内连接查询语句
select distinct e.deptno,d.dname from emp_lwx e inner join dept_lwx d on e.deptno=d.deptno;
分析上述 SQL 语句的内部执行顺序如下:
- 数据库先执行 from,打开表 emp_lwx 和 dept_lwx
- 接着执行 on,根据关联字段把两张表关联起来
- 接着执行 inner join,把匹配的数据取出生成一张虚表 v1
- 接着执行 select 子句,在虚表 v1 中取出相关的数据生成虚表 v2
- 接着执行 distinct,将虚表 v2 中 deptno 和 dname 都重复的数据过滤掉,生成虚表 v3,此虚表 v3 就是最后的查询结果
关键字 distinct 用法说明
select distinct deptno,job from emp_lwx;
distinct 关键字不是作用在字段 deptno 上,在执行 select 子句的时候,数据库是这样判断的,取出 deptno 和 job 的数据,这两个字段的数据联合起来在结果集中是唯一的就可以了,这个两个字段的数据就构成结果集中的一条记录,只要这条记录在整个结果集中是唯一的就OK了。
Oracle 数据库的分组排序查询
SELECT T.ENTITYID,T.CREDATE,T.EXACTCRETIME,ROW_NUMBER() OVER(PARTITION BY T.ENTITYID ORDER BY CREDATE DESC,EXACTCRETIME DESC) AS RNUM
FROM HYT2PRDHN.TASKED T;
说明:
先执行 FROM,接着执行 SELECT,接着执行 PARTITION BY,最后执行 ORDER BY。对 SELECT 出来的结果集按 ENTITYID 进行分组,每组再按 CREDATE 和 EXACTCRETIME 排序,顺序号的字段名为 RNUM,查询得到的结果如下图所示:
Oracle 数据库 cast 函数
SELECT CODE,NAME,CAST(CASE WHEN CODE LIKE '%000' THEN 1 WHEN CODE LIKE '%00' THEN 2 ELSE 3 END AS VARCHAR2(3)) AS LEV
FROM T_PF_DATADICT WHERE DDFLD='BNSCOPE' AND CODE IN ('08000','08100','08101','08102','08103','08200','08201','08300','08301')
ORDER BY CODE
解读:
CAST函数的作用是类型转换,在此就是将LEV 字段的数据类型转换成VARCHAR2(3)
Oracle 数据库 sum 函数的高级用法
select depcode,sum(case when BILLSTATE=1 then 1 else 0 end) as 未使用,sum(case when BILLSTATE in (2,3,4) then 1 else 0 end) as 已使用,sum(case when BILLSTATE in (5) then 1 else 0 end) as 已遗失 from BCBILLSTOCK group by depcode;
解读:
先对整个表进行遍历分组,然后判断每组里面每条记录 BILLSTATE 字段的值,如果是 1 则累加 1 ,否则累加 0,最后的累加值显示一列,列名为:未使用;如果是2或3或4则将累加 1,否则累加 0,最后的值显示一列,列名为:已使用;如果是 5 则累加 1,否则累加 0,最后的值显示一列,列名为:已遗失。
Oracle 数据库多层子查询嵌套查询
SELECT DEPNAME 运管机构,SUM(已作废) 已作废,SUM(已反馈) 已反馈,SUM(未使用) 未使用,SUM(已使用) 已使用
FROM
(SELECT DEPNAME,CASE 牌证状态 WHEN '已作废' THEN TOTAL END AS 已作废,CASE 牌证状态 WHEN '已反馈' THEN TOTAL END AS 已反馈,CASE 牌证状态 WHEN '未使用' THEN TOTAL END AS 未使用,CASE 牌证状态 WHEN '已使用' THEN TOTAL END AS 已使用
FROM
(SELECT D1.DEPNAME,B1.牌证状态,B1.TOTAL
FROM (SELECT T1.DEPCODE, CASE BILLSTATE WHEN '2' THEN '已使用' WHEN '3' THEN '已作废' WHEN '4' THEN '已反馈' WHEN '5' THEN '遗失' ELSE '未使用' END AS 牌证状态,SUM(CNT) TOTAL
FROM BCBILLSTOCK T1
GROUP BY DEPCODE,BILLSTATE) B1
LEFT JOIN HYT2PRDHN.T_PF_DEP D1
ON B1.DEPCODE=D1.DEPCODE))
GROUP BY DEPNAME;
注意: 先对某张表进行筛选再关联其它表是不可以的,对某个表先进行分组再筛选也是不可以的,会报错
关联子查询
select ename, salary, deptno from emp_xxx a where salary < ( select avg(nvl(salary,0))
from emp_xxx where deptno = a.deptno; // 子查询需要依赖主查询传递过来的参数 a.deptno
解读:
数据库的指针先指向 emp_xxx 的第一条记录,然后将当前记录的deptno的值传递给子查询,接着数据库开始执行子查询,计算出参数deptno的值所对应的部门的平均工资,接着又回到主查询判断当前记录的salary值是否小于平均工资,如果小于则添加到结果集,接着指针移到下条记录,重复上一次的查询动作,如果当前记录不小于平均工资,则直接将指针移到下条记录,重复上一次的查询动作。这样就可以查询出所有薪水比本部门平均工资低的员工数据。
我们知道数据库服务器执行SQL语句是有按照先后顺序的,例如:select ename,salary from emp_lwx where salary >3000;
顺序是这样的,数据库服务器首先打开emp_lwx表,然后执行where语句,按照where子句的条件来筛选符合条件的记录,服务器是对整个表从上至下进行全盘扫描,逐条判断记录是否符合条件,然后把符合条件的记录全部放在内存的一个虚表中,然后才执行select子句的,是符合条件的记录全部筛选出来后才执行select子句,而不是筛选一条记录就执行一次select子句,当然执行select子句也是从上至下逐条取出所需的数据,如果是组函数的话,那么就逐条记录取出所需的数据后再进行函数运算的。
数据库如何把纵向列表转换成横向列表
纵向列表,如下图所示:
如何变成横向列表,如下图所示:
SQL语句是这样写的:
select o.year,(select n.amount
from ym n where n.month='1' and n.year=o.year) as m1,(select n.amount
from ym n where n.month='2' and n.year=o.year) as m2,(select n.amount
from ym n where n.month='3' and n.year=o.year) as m3,(select n.amount
from ym n where n.month='4' and n.year=o.year) as m4
from ym o group by year;
解读下:
很明显这是一个关联子查询,执行顺序是这样的,首先主查询 from ym 0 group by year 是先打开ym这张表,然后根据year字段来分组,接着执行select语句,指针先移至第一组,获取第一组的year值,也就是1991,然后执行关联子查询了,这时会把第一组的年份1991传入子查询中,那么第一个子查询就根据 month=‘1’ and year=‘1991’ 获取到相应的 amount值,字段名是m1,接着执行第二个子查询了,同样是将第一组的年份1991传入,得到相应的amont值,直到4个子查询都执行完毕,这样就得到第一条记录。那么指针就移到第二组了,同上一轮一样取出相应的值,那么最后得到的结果就是第2条记录了。
注意:这里的指针按组移动,取到年份值后分别传给四个子查询!