oracle中优化left join的工作心得

本文分享了一次使用Oracle数据库处理数据时遇到的问题,通过将LEFT JOIN转换为WHERE子句进行优化,显著降低了查询开销,提高了效率。具体场景涉及A表和B表的联合查询,生成了一个根据B表标记的A表指定数列值的表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近领导要求一个任务,大致可以如下解释。

有A表和B表,两个表均有ID和DATE字段,A表存储一个完整的数列SEQ,B表描述了A数列的某段所携带的信息VAL,标记了起始数列号SEQ_START和终止数列号SEQ_END,要求生成一个根据B表标记A表指定数列VAL值的表


A表:

id     date              seq

1      2011/12/1   1

1      2011/12/1   2

1      2011/12/1   3

1      2011/12/2   1

1      2011/12/2   2

1      2011/12/2   3

2      2011/2/1      1

2      2011/2/1      2

2      2011/2/1      3

2      2011/2/1      4


B表:

id     date              seq_start     seq_end     val

1      2011/12/1   1                     2                   'val1'

1      2011/12/2   2                     3                   'val2'

2      2011/2/1     2                     3                   'val3'


完成表:

id     date              seq      val

1      2011/12/1   1           'val1'

1      2011/12/1   2           'val1'

1      2011/12/1   3

1      2011/12/2   1

1      2011/12/2   2           'val2'

1      2011/12/2   3           'val2'

2      2011/2/1      1

2      2011/2/1      2           'val3'

2      2011/2/1      3           'val3'

2      2011/2/1      4


根据以上条件写的语句:

select e.*,f.completion_id,f.completion_name,f.completion_number,f.top_md,f.bottom_md
from (
	select c.jh,d.create_date,c.yczmc,c.xch,d.cds,c.syds,c.syhd,c.yxhd,c.yxstl,c.dcjsjg,c.skqk
	from daa05@dzcxyh c,(
		select jh,create_date,
			count(completion_id) cds
		from (
			select a.well_desc jh,b.completion_id,
				to_date(to_char(b.create_date,'yyyy-MM-dd'),'yyyy-MM-dd') create_date
			from cd_well_source@a2 a,cd_completion_t@a2 b
			where b.well_id=a.well_id
		)
		group by jh,create_date
	) d
	where c.jh=d.jh
) e left join (
	select a.well_desc jh,
		to_date(to_char(b.create_date,'yyyy-MM-dd'),'yyyy-MM-dd') create_date,
		b.completion_id,b.completion_name,b.completion_number,
		nvl(b.top_md,0) top_md,
		nvl(b.bottom_md,0) bottom_md
	from cd_well_source@a2 a,cd_completion_t@a2 b
	where b.well_id=a.well_id
	order by a.well_desc
) f
on e.jh=f.jh and e.create_date=f.create_date and ((e.syds>=f.top_md and e.syds+e.syhd<=f.bottom_md) or (f.top_md=0 or f.bottom_md=0));

最后发现在最末端on的or条件开销太大

on e.jh=f.jh and e.create_date=f.create_date and ((e.syds>=f.top_md and e.syds+e.syhd<=f.bottom_md) or (f.top_md=0 or f.bottom_md=0))


于是把left join尽量都改写为where,同样的执行结果,where的开销远比left join小

优化后的

select g.*,h.completion_id,h.completion_name,h.completion_number,h.top_md,h.bottom_md
from (
	select c.jh,d.create_date,c.yczmc,c.xch,d.cds,c.syds,c.syhd,c.yxhd,c.yxstl,c.dcjsjg,c.skqk
	from daa05@dzcxyh c,(
		select jh,create_date,
			count(completion_id) cds
		from (
			select a.well_desc jh,b.completion_id,
				to_date(to_char(b.create_date,'yyyy-MM-dd'),'yyyy-MM-dd') create_date
			from cd_well_source@a2 a,cd_completion_t@a2 b
			where b.well_id=a.well_id
		)
		group by jh,create_date
	) d
	where c.jh=d.jh
) g left join (
	select e.*,f.completion_id,f.completion_name,f.completion_number,f.top_md,f.bottom_md
	from (
		select c.jh,d.create_date,c.yczmc,c.xch,d.cds,c.syds,c.syhd,c.yxhd,c.yxstl,c.dcjsjg,c.skqk
		from daa05@dzcxyh c,(
			select jh,create_date,
				count(completion_id) cds
			from (
				select a.well_desc jh,b.completion_id,
					to_date(to_char(b.create_date,'yyyy-MM-dd'),'yyyy-MM-dd') create_date
				from cd_well_source@a2 a,cd_completion_t@a2 b
				where b.well_id=a.well_id
			)
			group by jh,create_date
		) d
		where c.jh=d.jh
	) e ,(
		select a.well_desc jh,
			to_date(to_char(b.create_date,'yyyy-MM-dd'),'yyyy-MM-dd') create_date,
			b.completion_id,b.completion_name,b.completion_number,
			nvl(b.top_md,0) top_md,
			nvl(b.bottom_md,0) bottom_md
		from cd_well_source@a2 a,cd_completion_t@a2 b
		where b.well_id=a.well_id
		order by a.well_desc
	) f
	where e.jh=f.jh and e.create_date=f.create_date and ((e.syds>=f.top_md and e.syds+e.syhd<=f.bottom_md) or (f.top_md=0 or f.bottom_md=0))
) h
on g.jh=h.jh and g.create_date=h.create_date and g.xch=h.xch and g.syds=h.syds;




这样就是人类能忍受的程度了


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值