create table POLICY_PRODUCT_SIG
(
sig_policy_no VARCHAR2(20) not null,--个单号
product_code VARCHAR2(10) not null,--险种代码
is_primary_plan VARCHAR2(1) not null,--是否主险
product_status VARCHAR2(2) not null --险种状态
);
alter table SCOTT.POLICY_PRODUCT_SIG
add constraint PK_POLICY_PRODUCT_SIG primary key (PRODUCT_CODE, SIG_POLICY_NO);
//插入数据如下:
SQL> select sig_policy_no,product_code,is_primary_plan,product_status from scott.policy_product_sig order by sig_policy_no,product_code;
SIG_POLICY_NO PRODUCT_CODE IS_PRIMARY_PLAN PRODUCT_STATUS
---------------- ------------------ -------------------- -----------------
sig_policy_no_a prod_cde_1 Y 0
sig_policy_no_a prod_cde_2 Y 1
sig_policy_no_a prod_cde_3 Y 2
sig_policy_no_a prod_cde_4 N 2
sig_policy_no_b prod_cde_1 Y 0
sig_policy_no_b prod_cde_2 Y 0
sig_policy_no_b prod_cde_3 N 1
sig_policy_no_b prod_cde_4 N 0
sig_policy_no_c prod_cde_1 Y 2
sig_policy_no_c prod_cde_2 Y 0
sig_policy_no_c prod_cde_3 N 0
sig_policy_no_c prod_cde_4 N 0
sig_policy_no_d prod_cde_1 N 0
sig_policy_no_d prod_cde_2 N 1
sig_policy_no_d prod_cde_3 N 2
sig_policy_no_d prod_cde_4 N 0
16 rows selected
将前面的表数据,按sig_policy_no分组,在这里分别是sig_policy_no_a、sig_policy_no_b、sig_policy_no_c、sig_policy_no_d,找出同时满足is_primary_plan列至少有两个“Y”(即a b c)、product_status列至少有一个“1”(即a b d)、product_status列至少有一个“2”(即a c d)的sig_policy_no
select * from scott.policy_product_sig a
where
exists(select 1 -- 满足条件的有 a b d
from scott.policy_product_sig b
where a.sig_policy_no=b.sig_policy_no
and b.product_status = '1') and
exists(select 1 -- 满足条件的有 a c d
from scott.policy_product_sig b
where a.sig_policy_no=b.sig_policy_no
and b.product_status = '2') and
exists(select 1 -- 满足条件的有 a b c
from scott.policy_product_sig b
where a.sig_policy_no=b.sig_policy_no
and b.is_primary_plan = 'Y'
group by b.sig_policy_no
having count(1) > 1);
--全部满足条件的只有 a
--执行计划:
这条sql语句,对表scott.policy_product_sig执行了四次全表扫描,成本是21,逻辑读是31。如果scott.policy_product_sig是大表,这个查询是很可怕的。
select sig_policy_no,product_code,is_primary_plan,product_status from(
select sig_policy_no,product_code,is_primary_plan,product_status,
count(case when product_status='1' then 1 end) over(partition by sig_policy_no) product_status_cnt_1,
count(case when product_status='2' then 1 end) over(partition by sig_policy_no) product_status_cnt_2,
count(case when is_primary_plan='Y' then 1 end) over(partition by sig_policy_no) is_primary_plan_cnt
from scott.policy_product_sig
)where is_primary_plan_cnt>=2
and product_status_cnt_1>=1
and product_status_cnt_2>=1;
--执行计划:
改用分析函数之后,对表scott.policy_product_sig的全表扫描由四次降到了一次,成本由21降到了4,逻辑读由31降到了6,性能改善了很多。