0

我有一个如下所示的函数,由于光标循环,它的性能非常差。我需要有人帮我摆脱光标并改用一个语句。任何人都可以提供帮助将不胜感激!

function get_pat_liv_donor_trans_date(p_patr_id IN NUMBER) return date is
  v_transplant_date date;
  v_rst             date;
  v_patr_id         number;

  --get patient all the patr_id(s) which has been transplanted (kidney) with living donor
  cursor c_cur1 is
    select distinct patr.patr_id
      from pat,
           pat_register         patr,
           pat_register_org_det prod,
           transplant_org_det   tod,
           transplant           trans,
           don,
           don_org_con          doc,
           allo,
           all_pat_list         apl,
           ORG_SPEC             OS,
           DON_ORG_OFF_RES      DOOR
     where pat.pat_id = patr.pat_id
       and patr.patr_id = prod.patr_id
       and prod.prod_id = tod.prod_id --patient has been transplanted (kidney)
       and tod.orgsp_id in (5, 6, 7, 8, 9) --5:Kidney-Unknown, 6:Kidney-Right, 7:Kidney-Left, 8:Kidney-Both, 9:Kidney-Single
       and trans.patr_id = patr.patr_id
       and don.don_id = doc.don_id
       and doc.doc_id = allo.doc_id
       and allo.all_id = apl.all_id
       and apl.prod_id = prod.prod_id
       and don.cadaveric_flg = 'N' --living donor
       and OS.ORGSP_ID = DOOR.ORGSP_ID
       AND DOOR.ACCEPT_IND = 'Y'
       AND DOOR.ACCEPT_CANCEL_DATE IS NULL
       AND APL.APL_ID = DOOR.APL_ID
       and pat.pat_id in (select pat.pat_id
                            from pat, pat_register patr
                           where patr.patr_id = p_patr_id)
       and patr.patr_id not in -- Not suspend registration
           (select patr_id from pat_register_suspend where end_date is null)
          --Not canceled registration
       and patr.exp_date is null;

  --get patient transplant_date which has been transplanted (kidney) with living
  cursor c_cur2 is
    select min(distinct trans.transplant_date)
      from pat,
           pat_register         patr,
           pat_register_org_det prod,
           transplant_org_det   tod,
           transplant           trans,
           don,
           don_org_con          doc,
           allo,
           all_pat_list         apl,
           ORG_SPEC             OS,
           DON_ORG_OFF_RES      DOOR
     where pat.pat_id = patr.pat_id
       and patr.patr_id = prod.patr_id
       and prod.prod_id = tod.prod_id --patient has been transplanted (kidney)
       and tod.orgsp_id in (5, 6, 7, 8, 9) --5:Kidney-Unknown, 6:Kidney-Right, 7:Kidney-Left, 8:Kidney-Both, 9:Kidney-Single
       and trans.patr_id = patr.patr_id
       and don.don_id = doc.don_id
       and doc.doc_id = allo.doc_id
       and allo.all_id = apl.all_id
       and apl.prod_id = prod.prod_id
       and patr.patr_id = v_patr_id
       and don.cadaveric_flg = 'N' --living donor
       and OS.ORGSP_ID = DOOR.ORGSP_ID
       AND DOOR.ACCEPT_IND = 'Y'
       AND DOOR.ACCEPT_CANCEL_DATE IS NULL
       AND APL.APL_ID = DOOR.APL_ID;

begin
  --if patient current is Not waiting for pancreas
  if (tttt_kp_allocation.is_pat_waiting_for_pancreas(p_patr_id) != 'Y') then
    return v_rst;
  end if;

  open c_cur1;
  loop
    fetch c_cur1
      into v_patr_id;
    exit when c_cur1%notfound;

    open c_cur2;
    fetch c_cur2
      into v_transplant_date;

    if (v_rst is null) and (v_transplant_date is not null) then
      v_rst := v_transplant_date;
    end if;

    --get earlier of Date of Living Donor transplant for PAK
    if (v_rst is not null) and (v_transplant_date is not null) then
      if (v_rst - v_transplant_date > 0) then
        v_rst := v_transplant_date;
      end if;
    end if;

    close c_cur2;

  end loop;
  close c_cur1;

  return v_rst;
end;

c_cur1 将返回如下:

patr_id
1001
1002
1003
1004

c_cur2 将返回一个日期,如:

2001-jan-01   ( patr_id : 1001)
2002-jan-01   ( patr_id : 1002)
2003-jan-01   ( patr_id : 1003)
2004-jan-01   ( patr_id : 1004)

最终结果v_rst将获得从 (2001-jan-01, 2002-jan-01, 2003-jan-01, 2004-jan-01) 开始的最短日期

所以,我需要一种方法来摆脱游标循环(性能太差)并使用一条语句获得最终结果。

4

2 回答 2

0

您的查询c_cur1似乎不正确。它的结果不依赖于p_patr_id参数。
唯一提到的地方p_patr_id是以下子查询:

(select pat.pat_id
 from pat, pat_register patr
 where patr.patr_id = p_patr_id)

这个子查询的结果显然不依赖于p_patr_id. :-)

于 2013-03-20T20:45:03.347 回答
0

以下内容可能会对您有所帮助。


function get_pat_liv_donor_trans_date(p_patr_id IN NUMBER) return date is
  v_transplant_date date;
  v_rst             date;
  v_patr_id         number;
--get patient all the patr_id(s) which has been transplanted (kidney) with living donor
select case when v_rst is null and B.transplant_date is not null then v_rst := v_transplant_date
            when v_rst IS NOT NULL AND B.transplant_date is not null AND v_rst - v_transplant_date > 0 THEN v_rst := v_transplant_date
       END
from (
    select distinct patr.patr_id
      from pat,
           pat_register         patr,
           pat_register_org_det prod,
           transplant_org_det   tod,
           transplant           trans,
           don,
           don_org_con          doc,
           allo,
           all_pat_list         apl,
           ORG_SPEC             OS,
           DON_ORG_OFF_RES      DOOR
     where pat.pat_id = patr.pat_id
       and patr.patr_id = prod.patr_id
       and prod.prod_id = tod.prod_id --patient has been transplanted (kidney)
       and tod.orgsp_id in (5, 6, 7, 8, 9) --5:Kidney-Unknown, 6:Kidney-Right, 7:Kidney-Left, 8:Kidney-Both, 9:Kidney-Single
       and trans.patr_id = patr.patr_id
       and don.don_id = doc.don_id
       and doc.doc_id = allo.doc_id
       and allo.all_id = apl.all_id
       and apl.prod_id = prod.prod_id
       and don.cadaveric_flg = 'N' --living donor
       and OS.ORGSP_ID = DOOR.ORGSP_ID
       AND DOOR.ACCEPT_IND = 'Y'
       AND DOOR.ACCEPT_CANCEL_DATE IS NULL
       AND APL.APL_ID = DOOR.APL_ID
       and pat.pat_id in (select pat.pat_id
                            from pat, pat_register patr
                           where patr.patr_id = p_patr_id)
       and patr.patr_id not in -- Not suspend registration
           (select patr_id from pat_register_suspend where end_date is null)
          --Not canceled registration
       and patr.exp_date is null
    ) A 
    inner join ( 
    select patr.patr_id, min(trans.transplant_date)
      from pat,
           pat_register         patr,
           pat_register_org_det prod,
           transplant_org_det   tod,
           transplant           trans,
           don,
           don_org_con          doc,
           allo,
           all_pat_list         apl,
           ORG_SPEC             OS,
           DON_ORG_OFF_RES      DOOR
     where pat.pat_id = patr.pat_id
       and patr.patr_id = prod.patr_id
       and prod.prod_id = tod.prod_id --patient has been transplanted (kidney)
       and tod.orgsp_id in (5, 6, 7, 8, 9) --5:Kidney-Unknown, 6:Kidney-Right, 7:Kidney-Left, 8:Kidney-Both, 9:Kidney-Single
       and trans.patr_id = patr.patr_id
       and don.don_id = doc.don_id
       and doc.doc_id = allo.doc_id
       and allo.all_id = apl.all_id
       and apl.prod_id = prod.prod_id
       and patr.patr_id = v_patr_id
       and don.cadaveric_flg = 'N' --living donor
       and OS.ORGSP_ID = DOOR.ORGSP_ID
       AND DOOR.ACCEPT_IND = 'Y'
       AND DOOR.ACCEPT_CANCEL_DATE IS NULL
       AND APL.APL_ID = DOOR.APL_ID
     group by patr.patr_id
     ) B
     on A.patr_id = B.patr_id
  return v_rst;

于 2013-03-20T20:27:21.540 回答