Oracle分析函数-count(*) over(partition by 分组 order by 排序)

一.创建表与初始化数据

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

   --执行计划:

Oracle分析函数-count(*) over(partition by 分组 order by 排序)_第1张图片

这条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;

--执行计划:

Oracle分析函数-count(*) over(partition by 分组 order by 排序)_第2张图片

改用分析函数之后,对表scott.policy_product_sig的全表扫描由四次降到了一次,成本由21降到了4,逻辑读由31降到了6,性能改善了很多。

 

你可能感兴趣的:(ORACLE)