优化前SQL:
select rownum r,
a.*,
(select count(0) ymbjgrs
from (select c.xh, b.bjdm, count(*) bjgks
from cjb c
left join view_xsjbxx b
on c.xh = b.xh
where c.xn = '2016-2017'
and c.xq = '01'
and c.cj <
(select dycj from cjdzb where dydj like '%不及格%')
group by c.xh, b.bjdm)
where bjgks =1 or bjgks = 1
and bjdm = a.bjdm) ymbjgrs,
(select count(0) lmbjgrs
from (select c.xh, b.bjdm, count(*) bjgks
from cjb c
left join view_xsjbxx b
on c.xh = b.xh
where c.xn = '2016-2017'
and c.xq = '01'
and c.cj <
(select dycj from cjdzb where dydj like '%不及格%')
group by c.xh, b.bjdm)
where bjgks =1 or bjgks = 2
and bjdm = a.bjdm) lmbjgrs,
(select count(0) smbjgrs
from (select c.xh, b.bjdm, count(*) bjgks
from cjb c
left join view_xsjbxx b
on c.xh = b.xh
where c.xn = '2016-2017'
and c.xq = '01'
and c.cj <
(select dycj from cjdzb where dydj like '%不及格%')
group by c.xh, b.bjdm)
where bjgks =1 or bjgks = 3
and bjdm = a.bjdm) smbjgrs,
(select count(0) simbjgrs
from (select c.xh, b.bjdm, count(*) bjgks
from cjb c
left join view_xsjbxx b
on c.xh = b.xh
where c.xn = '2016-2017'
and c.xq = '01'
and c.cj <
(select dycj from cjdzb where dydj like '%不及格%')
group by c.xh, b.bjdm)
where bjgks =1 or bjgks = 4
and bjdm = a.bjdm) simbjgrs,
(select count(0) wmbjgrs
from (select c.xh, b.bjdm, count(*) bjgks
from cjb c
left join view_xsjbxx b
on c.xh = b.xh
where c.xn = '2016-2017'
and c.xq = '01'
and c.cj <
(select dycj from cjdzb where dydj like '%不及格%')
group by c.xh, b.bjdm)
where bjgks =1 or bjgks = 5
and bjdm = a.bjdm) wmbjgrs,
(select count(0) bjrs from view_xsjbxx d where d.bjdm = a.bjdm) bjrs,
(select avg(jd) from (
select AVG(d.jd) jd,c.bjdm bjdm,d.kcmc from view_xszz_xsjd_11799 d left join cjb b on d.xh = b.xh left join view_xsjbxx c on d.xh = c.xh where d.xn = '2016-2017' and b.xq = '01' group by c.bjdm,d.kcmc
) where bjdm = a.bjdm) jd,
(select avg(xf) from (
select c.bjdm bjdm,d.kcmc,avg(d.xf) xf from view_xszz_xsjd_11799 d left join cjb b on d.xh = b.xh left join view_xsjbxx c on d.xh = c.xh where d.xn = '2016-2017' and b.xq = '01' group by c.bjdm,d.kcmc
) where bjdm = a.bjdm) xf,
(select count(0) ksm
from (select kcmc
from CJB t
where xn = '2016-2017'
and xq = '01'
group by kcmc)) kskms
from (select a.nj || '!!luojw!!' || a.xydm || '!!luojw!!' || a.zydm ||
'!!luojw!!' || a.bjdm pk,
a.nj,
a.xymc,
a.xydm,
a.zydm,
a.zymc,
a.bjdm,
f.qqqh,
a.bjmc,
nvl(d.rs, 0) rs,
fdyxm,
bzrxm,
(case
when length(fdyxm) > 10 then
substr(fdyxm, 1, 10) || '...'
else
fdyxm
end) fdy,
(case
when length(bzrxm) > 10 then
substr(bzrxm, 1, 10) || '...'
else
bzrxm
end) bzr,
fdyzgh,
bzrzgh,
case
when fdyxm is null then
'否'
else
'是'
end sfyszfdy,
case
when bzrxm is null then
'否'
else
'是'
end sfyszbzr
from view_njxyzybj_all a
left join (select a.bjdm,
WM_CONCAT(a.zgh) fdyzgh,
WM_CONCAT(b.xm || ' ' || b.lxdh) fdyxm
from fdybjb a
left join fdyxxb b
on a.zgh = b.zgh
group by a.bjdm) b
on a.bjdm = b.bjdm
left join (select a.bjdm,
WM_CONCAT(a.zgh) bzrzgh,
WM_CONCAT(b.xm || ' ' || b.lxdh) bzrxm
from bzrbbb a
left join fdyxxb b
on a.zgh = b.zgh
group by a.bjdm) c
on a.bjdm = c.bjdm
left join (select bjdm, count(xh) rs
from xsxxb
where sfzx = '在校'
or sfzx is null
group by bjdm) d
on a.bjdm = d.bjdm
left join (select bjdm, count(xh) fzxrs
from xsxxb
where sfzx = '不在校'
group by bjdm) e
on a.bjdm = e.bjdm
left join (select bjdm, qqqh from XG_bjxxb_12303) f
on a.bjdm = f.bjdm
where (nvl(e.fzxrs, 0) = 0 and nvl(d.rs, 0) = 0)
or nvl(d.rs, 0) > 0
order by nj desc, xydm, zydm, bjdm) a
where 1 = 1
and (1 = 1);
优化后SQL:
select b.fdyxm,
a.nj,
a.zymc,
a.bjmc,
c.bjrs,
c.xy,
d.kskm,
round(f.xfs / c.bjrs,2) as pjxfjd,
i.ymbjgrs,
j.lmbjgrs,
k.smbjgrs,
l.simbjgrs,
m.wmbjgrs,
(i.ymbjgrs + j.lmbjgrs + k.smbjgrs + l.simbjgrs + m.wmbjgrs) as bjgzrs,
concat(round(nvl((i.ymbjgrs + j.lmbjgrs + k.smbjgrs + l.simbjgrs +
m.wmbjgrs) / c.bjrs,0) * 100,
2),
'%') as bjgbl
from view_njxyzybj a
left join (select a.bjdm,
WM_CONCAT(a.zgh) fdyzgh,
WM_CONCAT(b.xm) fdyxm
from fdybjb a
left join fdyxxb b
on a.zgh = b.zgh
group by a.bjdm) b
on b.bjdm = a.bjdm
left join (select count(xh) bjrs, bjdm,xy from xsxxb group by bjdm,xy) c
on c.bjdm = a.bjdm
left join (select count(0) kskm, bb.bjdm
from cjb aa
left join xsxxb bb
on aa.xh = bb.xh
group by bb.bjdm, aa.kcmc) d
on d.bjdm = a.bjdm
left join (select sum(a.xf * a.jd) / sum(a.xf) xfs, b.bjdm
from view_xszz_xsjd_11799 a
left join xsxxb b
on a.xh = b.xh
left join cjb c
on a.xh = c.xh
where c.xn = '2016-2017'
and c.xq = '01'
group by b.bjdm) f
on f.bjdm = a.bjdm
left join (select count(0) ymbjgrs, bjdm, bjgks
from (select c.xh, b.bjdm, count(*) bjgks
from cjb c
left join xsxxb b
on c.xh = b.xh
where c.xn = '2016-2017'
and c.xq = '01'
and c.cj <
(select dycj from cjdzb where dydj like '%不及格%')
group by c.xh, b.bjdm)
group by bjdm, bjgks) i
on i.bjdm = a.bjdm
and i.bjgks = 1
left join (select count(0) lmbjgrs, bjdm, bjgks
from (select c.xh, b.bjdm, count(*) bjgks
from cjb c
left join xsxxb b
on c.xh = b.xh
where c.xn = '2016-2017'
and c.xq = '01'
and c.cj <
(select dycj from cjdzb where dydj like '%不及格%')
group by c.xh, b.bjdm)
group by bjdm, bjgks) j
on i.bjdm = a.bjdm
and i.bjgks = 2
left join (select count(0) smbjgrs, bjdm, bjgks
from (select c.xh, b.bjdm, count(*) bjgks
from cjb c
left join xsxxb b
on c.xh = b.xh
where c.xn = '2016-2017'
and c.xq = '01'
and c.cj <
(select dycj from cjdzb where dydj like '%不及格%')
group by c.xh, b.bjdm)
group by bjdm, bjgks) k
on i.bjdm = a.bjdm
and i.bjgks = 3
left join (select count(0) simbjgrs, bjdm, bjgks
from (select c.xh, b.bjdm, count(*) bjgks
from cjb c
left join xsxxb b
on c.xh = b.xh
where c.xn = '2016-2017'
and c.xq = '01'
and c.cj <
(select dycj from cjdzb where dydj like '%不及格%')
group by c.xh, b.bjdm)
group by bjdm, bjgks) l
on i.bjdm = a.bjdm
and i.bjgks = 4
left join (select count(0) wmbjgrs, bjdm, bjgks
from (select c.xh, b.bjdm, count(*) bjgks
from cjb c
left join xsxxb b
on c.xh = b.xh
where c.xn = '2016-2017'
and c.xq = '01'
and c.cj <
(select dycj from cjdzb where dydj like '%不及格%')
group by c.xh, b.bjdm)
group by bjdm, bjgks) m
on i.bjdm = a.bjdm
and i.bjgks > 4
思路方面:首先要理清,哪张表作为主表,各个关联表和主表关系。将各个表与主表匹配的字段分析,哪些是需要用到的,哪些是可以舍弃的。
优化过程中遇到的问题和新get技能小结:
1.SQL语句报错,不是单组分组函数 --->首先,用聚合函数count(),sum()时,必须group by,其次要注意,单独的group by使用时,select后面不能是 * ,而应该是具体的要group by的列。
2.查询结果去重,比如现在查询一个学校的各个系及格人数,查询结果出来,一般有4条软件工程,4条机械工程,4条。。。原因是,每个学院又包含大一~大四的学生,故此处应该group by一下学院代码。
3.rownum和order by的执行顺序问题:
取网上一个例子:select id1,id2 from t_tablename where rownum<3 order by c_date desc
这个语句会先从结果集中取前三条记录,再对这3天记录按日期排序。如果设计者向先对日期排序,再取前三天记录,那么就不会得到正确的结果。
那么如果想得到先order by再rownum,则按如下操作:
select id1,id2 from (select id1,id2 from t_tablename order by c_date desc) where rownum<3
参考博客:https://blog.csdn.net/wulex/article/details/79996892
4.order by 和 group by的区别:
order by 从英文里理解就是行的排序方式,默认的为升序。 order by 后面必须列出排序的字段名,可以是多个字段名。
group by 从英文里理解就是分组。必须有“聚合函数”来配合才能使用,使用时至少需要一个分组标志字段。
在使用聚合函数时,使用group by 的目的就是要将数据分类汇总。
在sql命令格式使用的先后顺序上,group by 先于 order by。
参考博客:http://www.cnblogs.com/xiayang/articles/1395876.html
5.SQL中的nvl(column,0),nvl(column1,column2,column3),ifNull()区别
nvl()是oracle数据库中判断字段值是否为空的函数,
ifNull()是MySQL数据库中判断字段值是否为空的函数。
nvl(column1,column2)该函数目的是把一个空函数转为一个实际值。其中column1,column2的值可以是数字型、字符型、日期型,但是表达式1和表达式2的值必须是同一类型。
nvl(column,0):若column字段值为空,则返回0.
nvl(column1,column2,column3):若column1字段为空则返回column3,若不为空返回column2.
参考文档:https://blog.csdn.net/qq_24549805/article/details/51892651
6.round(m,n)函数
用于把m数值字段四舍五入n位,n为小数点后保留位数。
7.concat(m,n)函数
用于将字符串m和n连接起来,拼成一个新的字符串m+n。
例如除法运算后的小数,可以用concat(round(m/n,2) * 100,'%'),之所以要乘以100,是为了匹配后面的%,先将小数乘以100,再添加%,但*100运算,必须在round()函数的外面,如此才能不影响结果的精确性。
Oracle中 || 也可以用来拼接,例如:
select a.sybz1 || a.sybz2 || a.sybz3 as syd, a.bjdm, b.mzmc
from xsxxb a
left join mzdmb b
on a.mz = b.mzdm
其中sybz1存储省份,sybz2存储市级,sybz3存储县级,故返回值为省市县。
8.查询结果以百分比形式返回时,小数点前面的0消失,如图:
原因: oracle 数据库 字段值为小于1的小数时,使用char类型处理,会丢失小数点前面的0
解决方案: <1>使用decode函数:
既然小于1的小数首位必然是'.',那就判断首位是否为'.',是则在前面加上'0'即可
select decode(substr(num,1,1),'.','0'||num,num) from t1_number
<2>比较笨拙的方式:返回结果以小数返回,在页面和需要显示百分比的地方,做添加%处理。
9.TNS无监听程序:
出现原因:登录新数据库连接的时候出现,是数据库的链接地址有错。
解决方案:检查IP,端口和链接参数,与配置文件对比。
这应该属于比较低级错误,但我今日首次遇到,故记载之。