有效地从查询中获取总和

时间:2016-02-17 14:44:05

标签: plsql

我正在使用表格EQUIP,其中包含10M +行。虽然查询在几秒钟内执行,但运行for循环需要数小时。我觉得效率很低。它基本上采用与给定条件匹配的行的总和。请给我一个有效的方法来运行它。我为EXIPMNT创建了索引(mch_code,contract,CRE_DATE)

我需要分别得到每个M,P,T,X,E,D的总和

CURSOR get_cost_ IS
  SELECT EQUIP, COST
  FROM   EXIPMNT
  WHERE  mch_code = mch_code_
  AND contract = contract_
  AND CRE_DATE BETWEEN TO_DATE('01/01/' || year_, 'DD/MM/YYYY')
  AND TO_DATE('01/01/' || year_, 'DD/MM/YYYY') + INTERVAL '1' YEAR;

BEGIN

FOR rec_ IN get_cost_ LOOP
  IF (rec_. EQUIP = 'M') THEN
     material_ := material_ + nvl(rec_.cost, 0);
  ELSIF (rec_. EQUIP = 'P') THEN
     personal_ := personal_ + nvl(rec_.cost, 0);
  ELSIF (rec_. EQUIP = 'T') THEN
     tool_facility_ := tool_facility_ + nvl(rec_.cost, 0);
  ELSIF (rec_. EQUIP = 'X') THEN
     expense_ := expense_ + nvl(rec_.cost, 0);
  ELSIF (rec_. EQUIP = 'E') THEN
     external_ := external_ + nvl(rec_.cost, 0);
  ELSIF (rec_. EQUIP = 'D') THEN
     direct_sales_ := direct_sales_ + nvl(rec_.cost, 0);
  END IF; 

 NULL;
 END LOOP;

   total_cost_ := material_ + personal_ + tool_facility_ + expense_ + external_     + direct_sales_;

1 个答案:

答案 0 :(得分:2)

如果你真的只是在具有指定值的所有行的总和之后,那么这应该可以解决问题:

select sum(cost)
from   exipmnt
where  mch_code = mch_code_
and    contract = contract_
and    cre_date >= TO_DATE('01/01/' || year_, 'DD/MM/YYYY')
and    cre_date < TO_DATE('01/01/' || year_, 'DD/MM/YYYY') + INTERVAL '1' YEAR
and    equip in ('M', 'P', 'T', 'X', 'E', 'D');

否则,您可能会寻找以下其他方式:

在不同的行中显示每个装备值的总数(第三列显示所有行的完整总数:

select equip,
       sum(cost),
       sum(sum(cost)) over () total_cost
from   exipmnt
where  mch_code = mch_code_
and    contract = contract_
and    cre_date >= TO_DATE('01/01/' || year_, 'DD/MM/YYYY')
and    cre_date < TO_DATE('01/01/' || year_, 'DD/MM/YYYY') + INTERVAL '1' YEAR
and    equip in ('M', 'P', 'T', 'X', 'E', 'D')
group by equip;

将行转换为11g格式的列:

select sum(case when equip = 'M' then cost end) material_total,
       sum(case when equip = 'P' then cost end) personal_total,
       sum(case when equip = 'T' then cost end) tool_facility_total,
       sum(case when equip = 'X' then cost end) expense_total,
       sum(case when equip = 'E' then cost end) external_total,
       sum(case when equip = 'D' then cost end) direct_sales_total,
       sum(cost) total
from   exipmnt
where  mch_code = mch_code_
and    contract = contract_
and    cre_date >= TO_DATE('01/01/' || year_, 'DD/MM/YYYY')
and    cre_date < TO_DATE('01/01/' || year_, 'DD/MM/YYYY') + INTERVAL '1' YEAR
and    equip in ('M', 'P', 'T', 'X', 'E', 'D');

透视行11g样式:

select material_total,
       personal_total,
       tool_facility_total,
       expense_total,
       external_total,
       direct_sales_total,
       nvl(material_total, 0)
         + nvl(personal_total, 0)
         + nvl(tool_facility_total, 0)
         + nvl(expense_total, 0)
         + nvl(external_total, 0)
         + nvl(direct_sales_total, 0) total
from   (select *
        from   exipmnt
        where  mch_code = mch_code_
        and    contract = contract_
        and    cre_date >= TO_DATE('01/01/' || year_, 'DD/MM/YYYY')
        and    cre_date < TO_DATE('01/01/' || year_, 'DD/MM/YYYY') + INTERVAL '1' YEAR
        and    equip in ('M', 'P', 'T', 'X', 'E', 'D'))
pivot (sum(cost) as total for equip in ('M' as material,
                                        'P' as personal,
                                        'T' as tool_facility,
                                        'X' as expense,
                                        'E' as external,
                                        'D' as direct_sales));